Here's how I detect a closed connection when writing a TCP server. It always works for me.
First, I make every socket non-blocking, even the one I'll be using for
listen()ing:
Code:
#include <sys/socket.h> /* for socket(), PF_INET, and SOCK_STREAM */
#include <unistd.h> /* for fcntl() */
#include <fcntl.h> /* for fcntl() */
int fcntl_flags;
int socket_fd;
socket_fd=socket(PF_INET,SOCK_STREAM,0);
if(socket_fd==-1)
{
// error handling here
}
fcntl_flags=fcntl(socket_fd,F_GETFL,0);
if(fcntl_flags==-1)
{
// error handling here
}
if(fcntl(socket_fd,F_SETFL,fcntl_flags|O_NONBLOCK)==-1)
{
// error handling here
}
Then, when I've done the
listen(), I go into a
select() loop, waiting for activity. I include the read file descriptor for all sockets, including the listening one, even for any socket on which I might not want to read, but just write. I include the write file descriptor for all sockets on which I actually have data to send, but no others.
If the result value from
select() is -1 and
errn is
EINTR, I just go back and do another
select().
If, upon return from
select(), the listening socket seems to be ready to read, it's really ready to accept.
If, upon return from
select(), any other socket seems to be ready to read, I read from it. Even if only one byte. If the number of bytes I get back (as the result value from calling function
read() or
recv()) is -1 and
errno is
EINTR, I ignore this event and go back to do another
select(). But if the number of bytes I get back is 0, then the connection is broken.
That's all there is to it.