Read from socket freeze - c++

I have problem while reading data from client on server. The read() function will always freeze (block) after all data are readed and waiting for more data what is undesirable for me.
Server program:
soc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
sin.sin_addr.s_addr = INADDR_ANY;
bind(soc, (struct sockaddr*) &sin, sizeof(sin));
if (listen(soc, MAX))
return;
int socc; // socket for clinet
while (1) {
if ((socc = accept(soc, (struct sockaddr *) &sin, sinlen)) < 0)
break;
while ((result = read(socc, pointer, SIZE)) > 0) {
// after the data are readed, read function will block
}
// do some stuff and write reply to client => will never done
}
Client program:
...
soc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
struct sockaddr_in socketAddr;
socketAddr.sin_family = AF_INET;
socketAddr.sin_port = htons(port);
memcpy(&(socketAddr.sin_addr), host->h_addr, host->h_length);
if (connect(soc, (sockaddr *)&socketAddr, sizeof(socketAddr)) == -1)
return;
if (write(soc, req.c_str(), strlen(req.c_str())) < 0)
return;
The main problem is that I don't know how much data will be client sending to server, so the server should read all data from socket and after nothing is coming, leave the reading cycle. But the server read whole message for example (30 bytes) and waiting for more (but no more is coming). The sockets are still opened because the client is waiting for reply from server.

You will need to make your socket non-blocking. The read will immediately exit in that case if there is nothing to be read with a specific error.
Look at C- Unix Sockets - Non-blocking read

As stated earlier use non blocking or add RCV_TIMEOUT to socket.
struct timeval tv;
tv.tv_sec = 30; /* 30 Secs Timeout */
setsockopt(sockid, SOL_SOCKET, SO_RCVTIMEO,(struct timeval *)&tv,sizeof(struct timeval));

Related

C/C++: socket() creation fails in the loop, too many open files

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.

Asynchronous data reading from server using WinSock

I am using the WinSock API in C++ to connect and send data to a specific server (to increase readability, all the code is without error handling):
#include <winsock2.h>
#include <Windows.h>
#define PORT 5051
WSADATA WsaData;
WSAStartup(MAKEWORD(2, 2), &WsaData);
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
SOCKADDR_IN sin;
ZeroMemory(&sin, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr("Some valid IP");
connect(s, (sockaddr *) &sin, sizeof(sin));
string sdata_out = "Something like GET request\n";
send(s, sdata_out.c_str(), sdata_out.size(), 0);
The server will start to sending responses, separated by different periods of time. It will send responses without additional requests from me.
I need to read this data asynchronously (not cycle of recv() functions).
I tried to use WSAEventSelect() to listen on the local socket, like this:
SOCKET sloc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
SOCKADDR_IN sinloc;
ZeroMemory(&sinloc, sizeof(sinloc));
sinloc.sin_family = AF_INET;
sinloc.sin_port = htons(PORT);
sinloc.sin_addr.s_addr = INADDR_ANY;
WSAEventSelect(sloc, EventArray[EventTotal - 1], FD_ACCEPT |
FD_CLOSE | FD_READ | FD_CONNECT) == SOCKET_ERROR)
bind(sloc, (sockaddr *)&sinloc, sizeof(sinloc));
listen(sloc, 5));
I have no idea what to do further. I tried following this example, but my program got stuck at runtime on this code:
DWORD Event = WSAWaitForMultipleEvents(EventTotal, EventArray, FALSE, WSA_INFINITE, FALSE)
What is the problem? How should my event handler function look? Or, am I am doing something fundamentally wrong? Is there a correct way to asynchronously read data from the server, if I don't know when the data comes?

Set a timeout for recv from socket on Windows

Ih,
I think my code is correct but it doesn't work :(
To set a timeout for recv function on windows i know i must use this code:
DWORD timeout = 2000;
if (setsockopt(listenSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(DWORD)))
{ perror("setsockopt");
return -1;
}
But it doesn't work.
The code of my server is:
SOCKET listenSocket;
SOCKET remoteSocket= INVALID_SOCKET;
SOCKADDR_IN Server_addr;
SOCKADDR_IN Client_addr;
int sin_size;
short port;
int wsastartup;
int ls_result;
WORD wVersionRequested = 0x0202;
WSADATA wsaData;
wsastartup = WSAStartup(wVersionRequested, &wsaData);
if (wsastartup != NO_ERROR) cout << "Errore WSAStartup()" << endl;
listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
port = 4000;
Server_addr.sin_family = AF_INET;
Server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
Server_addr.sin_port = htons(port);
if (bind(listenSocket,(LPSOCKADDR) &Server_addr,sizeof(struct sockaddr)) < 0) {
cout << "Server: error bind." << endl;
closesocket(listenSocket);
return -1;
}
ls_result = listen(listenSocket, SOMAXCONN);
sin_size = sizeof(struct sockaddr_in);
remoteSocket = accept(listenSocket, (struct sockaddr *) &Client_addr, &sin_size);
// SET THE TIME OUT
DWORD timeout = 300;
if (setsockopt(remoteSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(DWORD)))
{ perror("setsockopt");
return -1;
}
int i=0;
while (i<50){
t_start = clock();
// when client receives the send below it wait 3 seconds and then trasmits the answer
send(remoteSocket, "code of start transmission", sizeof("code of start transmission"), 0);
recv_size=recv(remoteSocket, messaggio, sizeof(messaggio), 0);
printf("time for read= %f second \n", ((double)(end - t_start)) / CLOCKS_PER_SEC);
i=i+1;
}
The client when receives the message "code of start transmission" from servers, it wait 3 seconds and then aswer to server.
I expect time for read is 300 ms and recv_size<0, instead recv_size<0 but time for read is more or less 1.5 seconds (The server waits for the client's message). I don't understand why.
I'm on windows and i'm using eclipse and mingw-w64.
Please someone can help me??
Your code tries to use the socket after it has timed out. This is not a good idea because the socket is still somewhere in the middle of the failed blocking operation and in no shape to start a new operation. There's no way to unwind the portions of the operation that have previously completed and put the socket back where it was before the operation started.
Once a blocking socket operation times out, all you can safely do is close the socket. There is no support for undoing an operation that is partially completed and leaving the socket in any kind of sane state.
If a send or receive operation times out on a socket, the socket state is indeterminate, and should not be used[.] -- MSDN
The SO_RCVTIMEO socket option should never be used in code that's designed to work with sockets. It's a kludge to prevent infinite waits in code that wasn't designed to work with sockets natively. These aren't the droids you're looking for.
To set a timeout for recv function on windows i know i must use this code:
DWORD timeout = 2000;
if (setsockopt(listenSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(DWORD)))
{ perror("setsockopt");
return -1;
}
No. It should be an int, not a DWORD, but the main problem is that youre are here setting an accept() timeout, as this is the listening socket. You need to set it on the accepted socket(s).

Server socket finishes when client closes connection

I'm trying to create a server socket with C++ in order to accept one client connection at a time. The program successfully creates the server socket and waits for incoming connections but when a connection is closed by the client the program would loop endlessly. Otherwise if the connection is interrupted it would keep waiting for new connections as expected. Any idea why this is happening? Thanks
This is my C++ server code:
int listenfd, connfd, n;
struct sockaddr_in servaddr, cliaddr;
socklen_t clilen;
pid_t childpid;
char mesg[1000];
listenfd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(32000);
bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
listen(listenfd, 1024);
while (true) {
clilen = sizeof(cliaddr);
connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);
if ((childpid = fork()) == 0) {
close (listenfd);
while (true) {
n = recvfrom(connfd, mesg, 1000, 0, (struct sockaddr *)&cliaddr, &clilen);
sendto(connfd, mesg, n, 0, (struct sockaddr *)&cliaddr, sizeof(cliaddr));
mesg[n] = 0;
printf("%d: %s \n", n, mesg);
if (n <= 0) break;
}
close(connfd);
}
}
For some reason when the client closes the connection the program would keep printing -1: even with the if-break clause..
You never close connfd in parent process (when childpid != 0), and you do not properly terminate child process that will try to loop. Your if block should look like :
if ((childpid = fork()) == 0) {
...
close(connfd);
exit(0);
}
else {
close(connfd);
}
But as you say you want to accept one connection at a time, you can simply not fork.
And as seen in other answers :
do not use mesg[n] without testing n >= 0
recvfrom and sendto are overkill for TCP simply use recv and send (or even read and write)
mesg[n] = 0;
This breaks when n<0, ie. socket closed
The problem is your "n" and recvfrom. You are having a TCP client so the recvfrom won't return the correct value.
try to have a look on :
How to send and receive data socket TCP (C/C++)
Edit 1 :
Take note that you do the binding not connect() http://www.beej.us/guide/bgnet/output/html/multipage/recvman.html
means there is an error in recieving data, errno will be set accordingly, please try to check the error flag.
you've written a TCP server, but you use recvfrom and sendto which are specific for connection-less protocols (UDP).
try with recv and send. maybe that might help.

Socket listen doesn't unbind in C++ under linux

I have a socket that listens on some port.
I send the SIGSTOP signal to the thread that waits on the port (using accept) and terminate it. then I close the fd of the socket that I waited on. But for the next run of my project it doe's not allow me to listen on that port again.
My program is in C++ under linux.
What should I do?
Some parts of my code are:
Thread 1:
void* accepter(void *portNo) {
int newsockfd;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR opening socket");
}
struct sockaddr_in server;
bzero((char *) & server, sizeof (server));
server.sin_family = AF_INET;
server.sin_port = htons(*(int*) portNo);
server.sin_addr.s_addr = INADDR_ANY;
if (bind(sockfd, (struct sockaddr *) & server, sizeof (struct sockaddr_in)) < 0) {
perror("ERROR on binding");
}
listen(sockfd, 50);
while (true) {
struct sockaddr_in client;
socklen_t clientLen = sizeof (struct sockaddr_in);
newsockfd = accept(sockfd, (struct sockaddr *) & client, &clientLen);
if (accepterFlag) {
break;
}
if (getpeername(newsockfd, (sockaddr *) & client, &clientLen) == -1) {
perror("getpeername() failed");
}
sem_wait(setSem);
FD_SET(newsockfd, &set);
if (maxFd < newsockfd) {
maxFd = newsockfd;
}
sem_post(setSem);
}
Thread 2:
listenerFlag = true;
accepterFlag = true;
sleep(1);
pthread_kill(listenerThread, SIGSTOP);
pthread_kill(accepterThread, SIGSTOP);
close(sockfd);
sem_wait(setSem);
for (int i = 1; i <= maxFd; i++) {
if (FD_ISSET(i, &set)) {
close(i);
}
}
sem_post(setSem);
Thank you.
Did you know that sockets are typically kept in a kind of limbo for a minute or two after you've finished listening on them to prevent communications intended for the previous process coming to yours? It's called the 'TIME_WAIT' state.
If you want to override that behaviour use setsockopt to set the SO_REUSEADDR flag against the socket before listening on it.
I think the problem is that you have not properly closed the socket and/or your program.The socket probably still exists in the OS. check it with something like nestat -an. You should also check if your process has exited. If it has correctly ended, it should have closed your socket.
What you should do is :
interrupt your thread with a signal.
when interrupted your thread should cleanly close the socket before the end.
then you can cleanly exit from your program.
my2cents,