SERVER CODE
...
client_socket = accept(server_socket, (struct sockaddr *) &client_address, &client_address_len);
...
for (;;) {
if ( recv(client_socket, recived_buffer, MAX_MSG_LENGTH, 0) < 0 ) {
perror("ERROR leyendo el socket");
exit(1)
}
}
if i kill the client the server lopps indefinitely...
Any tip?
When a client closes a connection, the server-side recv() call will return a value of 0.
From the recv(2) manpage:
Return Value
These calls return the number of bytes received, or -1 if an error occurred. The return value will be 0 when the peer has performed an orderly shutdown.
It may also be important to note that the recv() call will block until there is data available to read. If you want to not block, you need to be sure to set the socket to non-blocking or use select() or poll() to see if there is incoming data before calling recv().
recv returns 0 - when the peer closes the connection, the other part interprets it as an EOF
Related
I've written a socket server program that sends a message to the client every 200ms in one thread (fork child process) and waits for getting data from the client in another thread. the problem is, if the server connection disconnected, no error won't raise. I've tried using signals (SIGPIPE) and checking errrno variable.
When I disconnect my server hotspot, data send to socket and no error display.
here's the code:
int ListeningForConnection(int Sockfd) {
int clilen = sizeof(Cli_addr);
int SocketId;
while(1) {
printf("waiting for new client...\n");
if ((SocketId = accept(Sockfd, (struct sockaddr *)&Cli_addr, (socklen_t *)&clilen)) < 0) {
printf("%s", "ERROR on accept. errno:%d : %s\n", errno, strerror(errno));
close(Sockfd);
return
}
printf("opened new communication with client\n");
if (fork() == 0)
SendDataToClient(SocketId);
else
GetDataFromClient(SocketId);
// if any error happen, should waiting for new client to connect.
}
return 0;
SendDataToClient:
while(1) {
int n;
if ((n = send(socket, SendData ,strlen(SendData), MSG_CONFIRM)) < 0) {
printf("%s\n", "ERROR writing to socket");
return;
}
printf ("%s No:%d %s \n ",SendData,n,strerror(errno));
delay(200);
}
When I disconnect my server hotspot, data send to socket and no error display.
The fault is not your program but your expectations.
TCP is robust against temporary disrupting the connectivity between the client and server application, and this is what you actually do when disconnecting the hotspot. TCP will recover from this once the connectivity is established again, i.e it will buffer unacknowledged data locally and retry sending these for some time.
I've tried using signals (SIGPIPE) and checking errrno variable.
Errors and/or SIGPIPE will happen if the TCP connection is actually closed but not on temporary disruptions. Closing can be done explicitly by either client or server or it can be done implicitly if unrecoverable delivery problems are detected, for example due to timeout or because of TCP keep-alive. If this is not (yet) the case the write to the socket will either succeed directly or the writing will block (if the socket is blocking) if no more space is inside the socket buffer.
For early detection of disrupted connectivity on idle connections use TCP keep-alive. For detecting problems delivering data use timeout for unacknowledged data.
I have a blocking accept() call in a thread that is waiting for connection requests. When the application is about to close, I want to signal the thread that is waiting on accept() to exit gracefully. I have found in the documentation for Winsock that I can set a timeout value for send() and recv(), but I can't do that for accept().
I have read that I can make the socket non-blocking and use select(), and pass a timeout value for select(), but I am looking for a solution for blocking sockets.
I have read that I can make the socket non-blocking and use select(), and pass a timeout value for select(), but I am looking for a solution for blocking sockets.
You can do this on blocking socket:
sock = socket(...);
bind(sock, ...);
listen(sock, ...);
while (program_running())
{
timeval timeout = {1, 0};
fd_set fds;
FD_ZERO(&fds);
FD_SET(sock, &fds);
select(sock+1, &fds, NULL, NULL, &timeout);
if (FD_ISSET(sock, &fds))
{
client = accept(sock, ...);
// do things with client
}
From MSDN accept function documentation:
The parameter readfds identifies the sockets that are to be checked for readability. If the socket is currently in the listen state, it will be marked as readable if an incoming connection request has been received such that an accept is guaranteed to complete without blocking.
I have a C socket client program where one thread is for receiving data and another for sending. If the server shuts down then the sender gets EPIPE. If I reconnect the same socket then it can receive data but the sender still gets EPIPE.
How to fix this?
Update:
Actually sender seems to send data as I see number of byte sent. But errno is still set to broken pipe. Before I only checked errno. Shouldn't it be changed to successful?
If I reconnect the same socket then it can receive data but the sender still gets EPIPE.
That can only mean that the sender is still sending via the old socket; also that you haven't closed the old socket.
sender seems to send data as I see number of byte sent. But errno is still set to broken pipe. Before I only checked errno. Shouldn't it be changed to successful?
No. It is only valid to check errno when an immediately prior system call has returned -1. Example:
int rc = send(...);
if (rc < 0)
{
if (errno == EWOULDBLOCK) // or EAGAIN *and* we are in non-blocking mode
{
// queue the write and return to the select() loop
}
else
{
perror("send"); // for example
}
}
else
{
// write succeeded ...
}
I am making a multi-threaded TCP server, when I use recv() in the threads, they do not update/execute/run infinitely (looping), unless recv() actually receives some data.
Here is a code snippet from inside the loop.
if( seconds < 15 ){
printf("%f seconds passed: \r", seconds);
if ( (read_size = recv(sock , client_message , 512 , 0)) > 0 )
{
//Send the message back to client
reply_message = client_message;
(void)write(sock, reply_message, strlen(reply_message));
}
}else{
// ... blah blah blah
}
If I comment out the internal IF statement, the thread runs & outputs printf() as fast as it can. When the IF statement is included, the thread waits on recv() and will not update ( printf() isn't printed ) until recv() has received data :/
Any ideas?
From recv(2) - Linux man page (see here):
If no messages are available at the socket, the receive calls wait for
a message to arrive, unless the socket is nonblocking (see fcntl(2)),
in which case the value -1 is returned and the external variable errno
is set to EAGAIN or EWOULDBLOCK. The receive calls normally return any
data available, up to the requested amount, rather than waiting for
receipt of the full amount requested.
So it's the way how recv works. If you want it to return immediately you should use non-blocking mode (see fcntl and select desriptions).
// sock is the socket you want to make non-blocking
int status = fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, 0) | O_NONBLOCK);
// handle the error
if(status == -1) {
...
}
If you want to check if there anything to read in socket
int count = 0;
ioctl(sock, FIONREAD, &count);
count is the number of bytes available in the socket
I need to perform some operations only after the time a TCP connection is fully closed, that's to say - all the data segments, as well as the finishing routine (FIN-ACK or RST) have been performed and done, and no packets will be sent on the wires.
Since closesocket() is not synchronous and could return before a full close of the connection and socket, I've used the SO_LINGER option to get the moment of closing.
According to the instructions in the MSDN for closesocket, and to the fact that my socket is non-blocking (and thus asynchronous), I wrote this code:
int ret;
/* config 2 secs of linger */
struct linger lng = {1, 2};
setsockopt(s, SOL_SOCKET, SO_LINGER, (const char*)&lng, sizeof(lng));
/* graceful close of TCP (FIN-ACK for both sides) */
shutdown(s, SD_BOTH);
/* linger routine for asynchronous sockets according to msdn */
do {
ret = closesocket(s);
} while (ret == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK);
/* my code to be run immediately after all the traffic */
printf("code to run after closing");
However, the closesocket call returns zero (success; instead of getting into the loop) and I see in Wireshark that my final printing is called before all the packets were sent, so - it looks like the linger isn't working.
By the way, the functions I used to open and connect the asynchronous socket were socket(), WSAIoctl() and its lpfnConnectEx() callback.
What's the reason that the lingered closesocket return before a full finish of the TCP connection? Is there a solution?