I'm writing a TCP communication script in c++ to communicate between my computer and an Aldebaran Nao robot.
In general my script is working. However, the trouble I am having is that when I call connect from the client (when the server application is closed or the ethernet connection removed) I get an error that the operation is in progress.
However, once the server application is restarted / ethernet cable reconnected, I still cannot call connect to successfully reestablish a connection. I still get an error that the operation is in progress.
As a note, whenever my client determines that a connection cannot be made, the socket descriptor is closed before reattempting a connection. Here is my code for connecting on the client side:
If there is any more information that would be useful, I would be happy to provide it. This project is relatively large, so I didn't want to include too much irrelevant information here.
TCPStream* TCPConnector::connect(const char* serverIP, int port, int timeoutSec)
{
if (timeoutSec == 0)
{
return connect(serverIP, port);
}
struct sockaddr_in address;
// Store all zeros for address struct.
memset(&address, 0, sizeof(address));
// Configure address struct.
address.sin_family = AF_INET;
address.sin_port = htons(port); // Convert from host to TCP network byte order.
inet_pton(PF_INET, serverIP, &(address.sin_addr)); // Convert IP address to network byte order.
// Create a socket. The socket signature is as follows: socket(int domain, int type, int protocol)
int sd = socket(AF_INET, SOCK_STREAM, 0);
int optval = 1;
if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval) == -1)
{
std::cout << "failed to set socket option" << std::endl;
}
// Set socket to be non-blocking.
int arg;
arg = fcntl(sd, F_GETFL, NULL);
arg |= O_NONBLOCK;
fcntl(sd, F_SETFL, arg);
// Connect with time limit.
fd_set set;
FD_ZERO(&set); // Clear the set.
FD_SET(sd, &set); // Add our file descriptor to the set.
struct timeval timeout;
timeout.tv_sec = timeoutSec;
timeout.tv_usec = 0;
// If the connect call returns 0, then the connection was established. Otherwise,
// check if the three-way handshake is underway.
if (::connect(sd, (struct sockaddr *)&address, sizeof(address)) < 0)
{
// If the handshake is underway.
if (errno == EINPROGRESS)
{
std::cout << "handshake in progress" << std::endl;
// Designate timeout period.
int ret = select(sd + 1, NULL, &set, NULL, &timeout);
std::cout << "return value from select : " << ret << std::endl;
// Check if timeout or an error occurred.
if (ret <= 0)
{
return NULL;
}
else
{
// Check if select returned 1 due to an error.
int valopt;
socklen_t len = sizeof(int);
getsockopt(sd, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &len);
if (valopt)
{
char * errorMessage = strerror( errno); // get string message from errn
std::string msg (errorMessage);
std::cout << msg << std::endl;
return NULL;
}
}
}
else
{
return NULL;
}
}
// Return socket to blocking mode
arg = fcntl(sd, F_GETFL, NULL);
arg &= (~O_NONBLOCK);
fcntl(sd, F_SETFL, arg);
// Create stream object.
return new TCPStream(sd, &address);
}
Your socket is non-blocking mode (you do it explicitly).
As a result, your connect will return immediately with 'connection is in progress'. When socket is non-blocking, you would need than to poll on this socket and wait for it to become readable and/or writeable - this would mean connection is completed (either successfully or not).
A better option in my view would be to use blocking sockets - I see no reason for you to use non-blocking call here.
Related
I am implementing a client-server TCP socket application. Client is on an OpenWRT Linux router (C based) and writes some data on the socket repeatedly and in a loop at some frequency rate. The Server is on a Linux Ubuntu machine (C/C++ based) and reads data in a loop according to data arrival speed.
Problem: Running the Server and then Client, server keeps reading new data. Both sides work well until the number of data deliveries (# of connections) reaches 1013. After that, the Client stuck at socket(AF_INET,SOCK_STREAM,0) with socket creation failed...: Too many open files. Apparently, the number of open fd approaches ulimit -n = 1024 on client.
I put the snippets of the code which shows the loop structures for Server.cpp and Client.c:
Server.c:
// TCP Socket creation stuff over here (work as they should):
// int sock_ = socket() / bind() / listen()
while (1)
{
socklen_t sizeOfserv_addr = sizeof(serv_addr_);
fd_set set;
struct timeval timeout;
int connfd_;
FD_ZERO(&set);
FD_SET(sock_, &set);
timeout.tv_sec = 10;
timeout.tv_usec = 0;
int rv_ = select(sock_ + 1, &set, NULL, NULL, &timeout);
if(rv_ == -1){
perror("select");
return 1;
}
else if(rv_ == 0){
printf("Client disconnected.."); /* a timeout occured */
close (connfd_);
close (sock_);
}
else{
connfd_ = accept (sock_,(struct sockaddr*)&serv_addr_,(socklen_t*)&sizeOfserv_addr);
if (connfd_ >= 0) {
int ret = read (connfd_, &payload, sizeof(payload)); /* some payload */
if (ret > 0)
printf("Received %d bytes !\n", ret);
close (connfd_); /* Keep parent socket open (sock_) */
}else{
printf("Server acccept failed..\n");
close (connfd_);
close (stcp.sock_);
return 0;
}
}
}
Client.cpp:
while (payload_exist) /* assuming payload_exist is true */
{
struct sockaddr_in servaddr;
int sock;
if (sock = socket(AF_INET, SOCK_STREAM, 0) == -1)
perror("socket creation failed...\n");
int one = 1;
int idletime = 2;
setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(one));
setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &idletime, sizeof(idletime));
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr("192.168.100.12");
servaddr.sin_port = htons(PORT); /* some PORT */
if (connect (sock, (struct sockaddr*)&servaddr, sizeof(servaddr)) != 0){
perror("connect failed...");
return 1;
}
write(sock, (struct sockaddr*)&payload, sizeof(payload)); /* some new payload */
shutdown(sock,SHUT_WR);
bool serverOff = false;
while (!serverOff){
if(read(sock, &res, sizeof(res)) < 0){
serverOff = true;
close(sock);
}
}
}
NOTE: payload is 800 bytes and always gets fully transmitted per one write action. Having both codes defined under int main(), the client keeps creating sockets and sending data, on the other side, server receives all and would automatically close() and leave if client terminates, due to using select(). If I don't terminate the Client, however, by checking some print logs, it is evident that Server successfully receives 1013 payloads before client crashes with socket creation failed...: Too many open files.
Update:
Following the point mentioned by Steffen Ullrich, it turned out that, the client socket fd has no leak, and the existence of a second fd in the original loop (which was left open) was making the ulimit exceed the limit.
if(read(sock, &res, sizeof(res)) < 0){
serverOff = true;
close(sock); /********* Not actually closing sock *********/
}
Your check for end of connection is wrong.
read returns 0 if the other side has shut down the connection and <0 only on error.
if (sock = socket(AF_INET, SOCK_STREAM, 0) == -1)
perror("socket creation failed...\n");
Given the precedence of operators in C this basically says:
sock = ( socket(AF_INET, SOCK_STREAM, 0) == -1) )
if (sock) ...
Assuming that socket(...) will not return an error but a file descriptor (i.e. >=0) the comparison will be false and thus this essentially says sock = 0 while leaking a file descriptor if the fd returned by socket was >0.
I try to write simple linux app that will accept http requests. I want to be able to stop listening thread so I use select().
Call sequence is
socket()->setsockopt()->bind()->listen()->select()->accept()->read()
When I send request from Chrome I get 451 bytes long buffer. Then select() immediately returns with success as well as accept() as if another request came. And then `read()' stops the thread waiting, because it has nothing to read.
socket() ok. listenSocket:3
bind() ok
listen() ok
select() got ready connection
accept() ok. socket: 4
reading...
read() ok. NRead: 451
listen() ok
select() got ready connection
accept() ok. socket: 5
reading...
What I do wrong?
What articles/books are worth to read to learn socket programming?
Best wishes,
Yura
Here is the simplified code:
void doServer()
{
const int trueFlag = 1;
m_socketListen = socket(AF_INET, SOCK_STREAM, 0);
// check m_socketListen
nRetVal = setsockopt(m_socketListen, SOL_SOCKET, SO_REUSEADDR, &trueFlag, sizeof(int));
// check
struct sockaddr_in addrServer;
bzero((char*)&addrServer, sizeof(addrServer));
addrServer.sin_family = AF_INET;
addrServer.sin_port = htons(DEFAULT_HTTP_PORT);
addrServer.sin_addr.s_addr = INADDR_ANY;
nRetVal = bind(m_socketListen, (const struct sockaddr* )&addrServer, sizeof(addrServer));
// check
struct sockaddr_in addrClient;
while (true)
{
bzero((char*)&addrClient, sizeof(addrClient));
unsigned int addrSize = sizeof(addrClient);
nRetVal = listen(m_socketListen, SOMAXCONN);
// check
struct timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
fd_set set;
FD_ZERO (&set);
FD_SET (m_socketListen, &set);
nRetVal = select (FD_SETSIZE, &set, NULL, NULL, &timeout);
// check
if (FD_ISSET(m_socketListen, &set))
{
int clientSocket = accept(m_socketListen,
(struct sockaddr*)&addrClient,
&addrSize);
int NRead;
char buffer[BUF_SIZE];
bzero(&buffer, BUF_SIZE);
NRead = read(clientSocket, &buffer, BUF_SIZE);
std::cout << "read() ok. NRead: " << NRead << std::endl;
}
}
}
I can't figure out how to send and receive multiple messages on the same source and destination ports. My server has to keep listening all the time, but sending is intermittent (can happen at random times) So technically sending and receiving should be on separate threads. Please help. Here is my code:
int main()
{
std::thread UDPServerControlThread (KNXUDPControlServer,60000); //start server to listen on port 60000
sendOneWayUDPMSG(SOMEDATA,DATASIZE); //I need this to send from the source port 60000 to the destination port 3671
//wait some random time, do some processing...
sendOneWayUDPMSG(MOREDATA,DATASIZE);
///more processing...
}
And here are the functions mentioned above:
void UDPControlServer(int serverPort)
{
struct sockaddr_in si_me, si_other;
int s, slen = sizeof
(si_other) , recv_len;
char buf[512];
//create a UDP socket
if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
{
DEBUG_MSG("CREATING UDP SOCKET FAILED" << endl);
}
// zero out the structure
memset((char *) &si_me, 0, sizeof(si_me));
si_me.sin_family = AF_INET;
si_me.sin_port = htons(serverPort);
//si_me.sin_addr.s_addr = htonl(INADDR_ANY);
//bind socket to port
if( ::bind(s , (struct sockaddr*)&si_me, sizeof(si_me) ) == -1)
{
DEBUG_MSG("BINDING SOCKET TO PORT FAILED" << endl);
}
//keep listening for data
while(1)
{
//printf("*CONTROL-SERVER Waiting for data...");
fflush(stdout);
if ((recv_len = ::recvfrom(s, buf, 512, 0, (struct sockaddr *) &si_other, (socklen_t*)&slen)) == -1)
{
DEBUG_MSG("*CONTROL-SERVER RECEIVING FROM SOCKET FAILED" << endl);
}
}
}
And this Function:
void sendOneWayUDPMSG(unsigned char * messagePayload, int messageSize)
{
struct sockaddr_in si_in;
int s, slen_in=sizeof(si_in);
//char buf[512];
if ( (s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
{
DEBUG_MSG("FAILED TO CREATE SOCKET" << endl);
}
memset((char *) &si_in, 0, sizeof(si_in));
si_in.sin_family = AF_INET;
si_in.sin_port=htons(3671); // port
if (::inet_aton(KNXIPInterfaceAddress.c_str() , &si_in.sin_addr) == 0)
{
fprintf(stderr, "inet_aton() failed\n");
exit(1);
}
//send the message
if (sendto(s, messagePayload, messageSize , 0 , (struct sockaddr *) &si_in, slen_in)==-1)
{
DEBUG_MSG("SEND TO SOCKET FAILED" << endl);
}
close(s);
}
To summarize, my code basically listens on port 60000 and sends data to the external server on its local port of 3671. But those packets that are sent are sent from random source ports. I need them to be sent on port 60000 as well.
My server has to keep listening all the time, but sending is intermittent (can happen at random times) So technically sending and receiving should be on separate threads.
Not exactly. You should be multiplexing your I/O using select, poll, or possibly even epoll.
If you want to have the same source port on outgoing packets as the port that you're receiving packets, just re-use the socket descriptor you get here in your UDPControlServer function...
if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
{
DEBUG_MSG("CREATING UDP SOCKET FAILED" << endl);
}
in your sendOneWayUDPMSG function.
I am getting Transport endpoint is not connected error in UDP server program, while I am try to
shutdown the socket via shutdown(m_ReceiveSocketId, SHUT_RDWR);
Following is my code snippet:
bool UDPSocket::receiveMessage()
{
struct sockaddr_in serverAddr; //Information about the server
struct hostent *hostp; // Information about this device
char buffer[BUFFERSIZE]; // Buffer to store incoming message
int serverlen; // to store server address length
//Open a datagram Socket
if((m_ReceiveSocketId = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
Utility_SingleTon::printLog(LOG_ERROR,"(%s %s %d) UDP Client - socket() error",__FILE__,__func__, __LINE__);
pthread_exit(NULL);
return false;
}
//Configure Server Address.
//set family and port
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(m_ListeningPort);
if (bind(m_ReceiveSocketId, (struct sockaddr *) &serverAddr,sizeof(struct sockaddr_in)) < 0 )
{
Utility_SingleTon::printLog(LOG_ERROR,"(%s %s %d) UDP Client- Socket Bind error=%s",__FILE__,__func__, __LINE__,strerror(errno));
pthread_exit(NULL);
return false;
}
//TODO Re-Route Mechanism.
if((serverAddr.sin_addr.s_addr = inet_addr(m_ServerIPStr.c_str())) == (unsigned long)INADDR_NONE)
{
/* Use the gethostbyname() function to retrieve */
/* the address of the host server if the system */
/* passed the host name of the server as a parameter. */
/************************************************/
/* get server address */
hostp = gethostbyname(m_ServerIPStr.c_str());
if(hostp == (struct hostent *)NULL)
{
/* h_errno is usually defined */
/* in netdb.h */
Utility_SingleTon::printLog(LOG_ERROR,"%s %d %s %s %d", "Host Not found", h_errno,__FILE__,__func__, __LINE__);
pthread_exit(NULL);
return false;
}
memcpy(&serverAddr.sin_addr, hostp->h_addr, sizeof(serverAddr.sin_addr));
}
serverlen = (int )sizeof(serverAddr);
// Loop and listen for incoming message
while(m_RecevieFlag)
{
int receivedByte = 0;
memset(buffer, 0, BUFFERSIZE);
//receive data from the server
receivedByte = recvfrom(m_ReceiveSocketId, buffer, BUFFERSIZE, 0, (struct sockaddr *)&serverAddr, (socklen_t*)&serverlen);
if(receivedByte == -1)
{
Utility_SingleTon::printLog(LOG_ERROR,"[%s:%d#%s] UDP Client - receive error",__FILE__,__LINE__,__func__);
close(m_ReceiveSocketId);
pthread_exit(NULL);
return false;
}
else if(receivedByte > 0)
{
string rMesg;
rMesg.erase();
for(int loop = 0; loop < receivedByte; loop++)
rMesg.append(1, buffer[loop]);
Utility_SingleTon::printLog(LOG_DEBUG,"[%s:%d#%s] received message=%d",__FILE__,__LINE__,__func__, rMesg.length());
QOMManager_SingleTon::getInstance()->setReceivedMessage(rMesg);
raise(SIGUSR1);
}
}
close(m_ReceiveSocketId);
pthread_exit(NULL);
return true;
}
Any help would be appreciated.
Thanks Yuvi.
You don't need to call shutdown() for a UDP socket. From the man page:
The shutdown() call causes all or part of a full-duplex connection on the socket
associated with sockfd to be shut down.
If you call shutdown() on a UDP socket, it will return ENOTCONN
(The specified socket is not connected) because UDP is a connectionless protocol.
All you need to do is close the socket and set the socket to INVALID_SOCKET. Then in your destructor check whether the socket has already been set to INVALID_SOCKET before closing it.
I am writing some simple client/server code using UDP. The program works fine, but if I only start the client, the recvfrom method does not block. However, when I remove the sendto method, recvfrom starts to block. Any idea of what is going on?
Here is the client side code:
int server_length; /* Length of server struct */
char send_buffer[256] = "hi"; /* Data to send */
time_t current_time; /* Time received */
while(true)
{
/* Tranmsit data to get time */
server_length = sizeof(struct sockaddr_in);
if (sendto(m_oSocket, send_buffer, (int)strlen(send_buffer) + 1, 0, (struct sockaddr *)&m_oServer, server_length) == -1)
{
fprintf(stderr, "Error transmitting data.\n");
continue;
}
/* Receive time */
if (recvfrom(m_oSocket, (char *)¤t_time, (int)sizeof(current_time), 0, (struct sockaddr *)&m_oServer, &server_length) < 0)
{
fprintf(stderr, "Error receiving data.\n");
continue;
}
/* Display time */
printf("Current time: %s\n", ctime(¤t_time));
Sleep(1000);
}
And here is the initialization:
unsigned short m_iPortnumber;
struct sockaddr_in m_oServer;
struct sockaddr_in m_oClient;
SOCKET m_oSocket;
WSADATA w; /* Used to open Windows connection */
int a1, a2, a3, a4; /* Server address components in xxx.xxx.xxx.xxx form */
a1 = 192;
a2 = 168;
a3 = 2;
a4 = 14;
m_iPortnumber = 52685;
/* Open windows connection */
if (WSAStartup(0x0101, &w) != 0)
{
fprintf(stderr, "Could not open Windows connection.\n");
exit(0);
}
/* Open a datagram socket */
m_oSocket = socket(AF_INET, SOCK_DGRAM, 0);
if (m_oSocket == INVALID_SOCKET)
{
fprintf(stderr, "Could not create socket.\n");
WSACleanup();
exit(0);
}
/* Clear out server struct */
memset((void *)&m_oServer, '\0', sizeof(struct sockaddr_in));
/* Set family and port */
m_oServer.sin_family = AF_INET;
m_oServer.sin_port = htons(m_iPortnumber);
/* Set server address */
m_oServer.sin_addr.S_un.S_un_b.s_b1 = (unsigned char)a1;
m_oServer.sin_addr.S_un.S_un_b.s_b2 = (unsigned char)a2;
m_oServer.sin_addr.S_un.S_un_b.s_b3 = (unsigned char)a3;
m_oServer.sin_addr.S_un.S_un_b.s_b4 = (unsigned char)a4;
/* Clear out client struct */
memset((void *)&m_oClient, '\0', sizeof(struct sockaddr_in));
/* Set family and port */
m_oClient.sin_family = AF_INET;
m_oClient.sin_addr.s_addr=INADDR_ANY;
m_oClient.sin_port = htons(0);
/* Bind local address to socket */
if (bind(m_oSocket, (struct sockaddr *)&m_oClient, sizeof(struct sockaddr_in)) == -1)
{
fprintf(stderr, "Cannot bind address to socket.\n");
closesocket(m_oSocket);
WSACleanup();
exit(0);
}
There are a variety of ways that sendto can fail. Some, such as arp failure, will cause an error during sendto. Other, such as ICMP port unreachable, may be reported when you next use the socket.
Your recvfrom call could actually be fetching the ICMP packet sent in response to your outgoing packet.
Does a second recvfrom block as expected?
Socket required to be set BLOCKING/NON-BLOCKING.
Set BLOCKING
int nMode = 0; // 0: BLOCKING
if (ioctlsocket (objSocket, FIONBIO, &nMode) == SOCKET_ERROR)
{
closesocket(SendingSocket);
WSACleanup();
return iRet;
}
Set NON-BLOCKING
int nMode = 1; // 1: NON-BLOCKING
if (ioctlsocket (objSocket, FIONBIO, &nMode) == SOCKET_ERROR)
{
closesocket(SendingSocket);
WSACleanup();
return iRet;
}
It looks like you're setting up the server socket and the client socket the same way. The initialization looks good for a server, but for the client, you'll want to bind to port 0.
In fact, for both of them you can do INADDR_ANY (IP 0.0.0.0), which doesn't bind to a specific interface, but instead allows any connection on the correct port.