Click to See Complete Forum and Search --> : select() and detection of closed socket


nickptar
08-02-2004, 11:14 PM
The select_tut(2) man page seems to imply that to check if a socket is closed, you use the exceptfds parameter (which it says is used for out-of-band data), as in this code:


if (fd1 > 0)
if (FD_ISSET (fd1, &er)) {
char c;
errno = 0;
r = recv (fd1, &c, 1, MSG_OOB);
if (r < 1) {
SHUT_FD1;
} else
send (fd2, &c, 1, MSG_OOB);
}


Is this accurate, or is there some other way? It seems to me that this would be a rather clumsy way to notify the program.

Also, if you're doing straight TCP input and output, do send() and recv() have any advantages over read() and write()?

bwkaz
08-02-2004, 11:33 PM
With TCP, no I don't believe send and recv do anything different from read and write. (Actually I think of UDP as a bit of a performance hack anyway. At least with TCP sockets you can use the same system calls as you'd be able to use with a file, which makes testing a little easier -- just use a file handle instead of a socket handle while testing. Not to mention the number of times I've seen people try to implement connections on top of UDP because "UDP is faster!" Duh... yeah it is, but only because it doesn't do what you need it to do...)

To check whether a socket is closed, just try to read() from it. If read() returns 0, then it's been closed. (However, if you call read() again, it will return -1.) The only reason to use select() is if you have more than one file descriptor that you're waiting on, and from your question, it sounds like you only have one. Let read() do the blocking for you rather than select().

nickptar
08-02-2004, 11:41 PM
Originally posted by bwkaz
To check whether a socket is closed, just try to read() from it. If read() returns 0, then it's been closed. (However, if you call read() again, it will return -1.) The only reason to use select() is if you have more than one file descriptor that you're waiting on, and from your question, it sounds like you only have one. Let read() do the blocking for you rather than select().

Except I need to have large numbers of sockets open at once, some waiting to read, some waiting to write. I suppose I could set O_NONBLOCK and loop through, read()ing all of them and seeing if they return 0, but that would not be efficient. Can select() report socket closings?

tecknophreak
08-04-2004, 11:14 AM
Originally posted by nickptar
Except I need to have large numbers of sockets open at once, some waiting to read, some waiting to write. I suppose I could set O_NONBLOCK and loop through, read()ing all of them and seeing if they return 0, but that would not be efficient. Can select() report socket closings?

With the large number of sockets open at once, use select. Yes, using the O_NONBLOCK will use up way too much cpu. Select will only tell you that there has been activity on the socket(or file descripter). When you go in and read/write and get a 0 like bwkaz said, then you've been closed.

Also, you'll probably want to add a SIGPIPE(believe that's the one) check in there, in case you're connection(s) go to crap.

nickptar
08-04-2004, 11:33 AM
Originally posted by tecknophreak
With the large number of sockets open at once, use select. Yes, using the O_NONBLOCK will use up way too much cpu. Select will only tell you that there has been activity on the socket(or file descripter). When you go in and read/write and get a 0 like bwkaz said, then you've been closed.

Also, you'll probably want to add a SIGPIPE(believe that's the one) check in there, in case you're connection(s) go to crap.

I'm confused. I know that I can check if a socket is dead by seeing if read() returns 0, but if it's dead, select() will never mark it as available for reading, right? So how will the program - blocking in select() and only calling read() or write() when select() says to - know when the socket closes? Is the "exceptids" parameter for this, as well as out-of-bound data?

What function can raise SIGPIPE, and under what circumstances?

tecknophreak
08-04-2004, 12:45 PM
Can't remember off hand what would cause a SIGPIPE, but I remember that it does happen occationally and it killed the program I was working on.

select will exit when a connection has been broken. The man page tells you that

Those listed in readfds will be watched to see if characters become available for reading (more precisely, to see if a read will not block - in particular, a file descriptor is also ready on end-of-file)

When a connection is broken, then that socket will not block on a read or write.

bwkaz
08-04-2004, 06:26 PM
Didn't you post earlier that you could use exceptfds for checking for a closed connection?

I'm still pretty sure that's the case -- select will return if any FD in readfds is ready to read, any FD in writefds is ready to write, OR any socket FD in exceptfds either has out-of-band data, or has been closed. At least, that's how I read the select (and select_tut) manpage...