2

I'm using Linux.

Can someone provide me an example of how to use select() or poll() to check whether a TCP connection was closed by peer through FIN or terminated by RST?

poll() can detect RST with setting POLLHUP or POLLERR in revents, but select() has no facilities like this.

In my test, when socket is terminated by RST, socket error got by getsockopt will be ECONNRESET. Is this a effective way or not?

Is it necessary to determine how the connection was closed?

Thanks!

Vincent Xue
  • 969
  • 1
  • 7
  • 17
  • 2
    "*How to check if a TCP connection was closed by peer gracefully*": A `recv()` would return 0. – alk Aug 07 '16 at 15:49
  • @alk, I don't want to read from the socket, is there any other way? – Vincent Xue Aug 07 '16 at 15:51
  • @alk You are thinking about -1 A return of 0 is valid. http://linux.die.net/man/2/read – Johnny V Aug 07 '16 at 16:39
  • 1
    @JohnnyV: I did not mention `-1` by intention, as the error case was not asked. And yes, 0 is valid. If `recv()` returns `0`, this indicates that the other side orderly shut down the connection. For reference: http://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html – alk Aug 07 '16 at 17:30
  • @alk I guess it depends if the sockets are non blocking or not because recv() is a blocking call. Calling read() on a non blocking socket may return 0 and not mean that the socket is closed. For non blocking, you have to rely on the errors. – Johnny V Aug 07 '16 at 17:39
  • 1
    @JohnnyV: "*Calling `read()` on a non blocking socket may return 0 and not mean that the socket is closed.*": This is not correct. If a non-blocking socket does not find any data on reading/receiving it returns `-1` and sets `errno` to `EAGAIN` or `EWOULDBLOCK` else it returns the number of bytes received. BTW, I provided the link to the specifications already. – alk Aug 07 '16 at 17:43
  • @alk Oh my bad! I've been in Java land too long. https://searchcode.com/codesearch/view/17994360/ -> convertReturnVal() – Johnny V Aug 07 '16 at 17:53

1 Answers1

0

If the socket was closed gracefully, the socket will be set for read. Then, when you read, you will receive 0 data read because you got to EOF. You can also check with

ioctl(sock, FIONREAD, &n);

to determine if there is data to read. Here you have an example: c++ how to use select to see if a socket has closed

According to select man: "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)"

If there is a pending socket error, the corresponding bit will be set in readfds or writefds. Then read or recv should return error. Also you can use this to determine if there is a pending error in the socket:

if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &result, &resultLen) < 0) {
    //getsockopt ERROR
} else if (result == 0) {
    //NO ERROR
} else {
    //SOCKET ERROR
}
Community
  • 1
  • 1
rodolk
  • 5,606
  • 3
  • 28
  • 34
  • The `ioctl(FIONREAD...)` has nothing to do with it. There is a difference between 'closed gracefully' and 'no data available to be read without blocking'. – user207421 Aug 15 '16 at 22:44
  • @EJP, if there is no data available, select will not return setting the corresponding bit in readfds. It will set that bit either because there is data available, the socket was closed gracefully, or there is a pending error. You detect the pending error with getsockopt as indicated, if no error then you check if there is data available to read. Then the only reason why there is no data available is because the socket was closed. – rodolk Aug 16 '16 at 14:44
  • Or another thread beat you to reading it. The correct technique is to do the `recv()` and identify the zero return value. Tricks like this are both unreliable and pointless. – user207421 Aug 22 '16 at 01:24
  • @EJP, there is no trick here. It's the way to do it. You can use recv, read, as I mentioned, or ioctl. If you are talking about multi-threading this is a totally different story that affects ioctl, recv or any other technique if it is not handled correctly in order to avoid race conditions. – rodolk Aug 22 '16 at 05:36