Is socket still connected?

Started by
11 comments, last by nevernomore 18 years, 10 months ago
Hi, I'm kinda new to low level socket work. I know that TCP sockets 'guarantee' a connection, but I'm - for some reason - unable to detect (in a nice way) if the other side has closed the connection. I'm accepting a call, serving the accepted socket, but cannot tell when the other side has closed it. I could try and send something over it and if it returns an error, assume that the connection was lost. But I'd like an IsConnected method for my socket class. How is that reliably done? At the moment foremost WinSock, but Posix would be nice to know as well. tia, CipherCraft PS I've searched everywhere - I think [wink] - but cannot find something conclusive... Nor something that actually works.
Advertisement
You can try doing a read of 0 bytes, but that won't detect a disconnected socket in all cases (like if they did non "clean" disconnect, or they just closed the socket without calling shutdown, etc). The only reliable way is with a "ping" type method where you send the remote host a packet and wait for it to reply.
On some OSs there is an option you can enable on TCP sockets, SO_KEEPALIVE.

This will periodically send a TCP keepalive packet on an otherwise idle connection (this is not visible to the application).

If this keepalive fails (i.e. does not respond, or responds negatively), the application will then be notified in the usual way. In UNIX it's also sent a SIGPIPE.

I say the "usual way" - the socket will have an error flagged, and a select on it will succeed - the next attempt to read anything will give an error of timed out of connection reset - the socket should then be closed (otherwise, the next attempt to select or read, will again flag the same error until the socket is closed).

A TCP socket can't be used any more once it enters this error state and will stay that way until it's closed.

This SO_KEEPALIVE option avoids the application needing to create its own keepalive messages. I believe that even if your OS does not support setting SO_KEEPALIVE on local sockets, it will still behave correctly if they're set on the remote end.

Mark
yeah tcp socket option check for peer status with SO_KEAPALIVE .
Is this winsock or raw socket?

Kuphryn
The other side could also start a shutdown negotiation using the shutdown() call.
enum Bool { True, False, FileNotFound };
Hi,

@Dean:
I've tried the read 0 bytes approach, using MSG_PEEK and such, but you're right: it doesn't work for all cases it seems. Pinging is not the solution, since I 'know' the other side is present; I just like to know if the connection is still valid/active.

@markr & rzcodeman:
I've thought about this, but it's not so much that I would like to keep the connection, I just like to detect if the other side has closed it.

@kuphryn:
The code is part of a library for win32 and *nix (mostly posix calls). I'm creating the sockets using ::socket () and accept them using ::accept (). I'm uncertain what you mean by winsock as opposed to raw socket; could you explain?

@hplus0603:
I have shutdown in place at my end, yes: first for send only and second for both. The other side I'm not sure: not my code. I assume it would be best if they did, because, if I understand correctly, both sides negotiate when shutdown calls are made? That would cleanly shut it down, I guess, but how can I tell without trying to read and get an error?

Thanks for your input so far. I've tried the suggestions but came up empty: mb because the other side doesn't close properly, mb because I'm missing some knowledge. I just find it strange that a ::connected () call or something like that doesn't exist.

cu,
CipherCraft
Quote:Original post by CipherCraft
I've tried the read 0 bytes approach, using MSG_PEEK and such, but you're right: it doesn't work for all cases it seems. Pinging is not the solution, since I 'know' the other side is present; I just like to know if the connection is still valid/active.

When he says pinging, he doesn't mean an ICMP ping. He means a small injection into the TCP stream which the other side ignores but acknowledges, demonstrating that the TCP connection still works.

Quote:
I've thought about this, but it's not so much that I would like to keep the connection, I just like to detect if the other side has closed it.

The keepalive option doesn't do anything to "keep" the connection "alive"; it just sends dummy data through it from time to time. Either side can still terminate the connection. (Things that detect network inactivity, though, will not work; for instance, a dialup connection will not timeout.)

I think you're a little confused about what it means for a connection to be open. TCP creates a "virtual circuit" on a "datagram network". What that means, is that TCP/IP pretends to your application that you have this continuous, linear streaming circuit available directly from point A to point B, when in fact really it's discrete packets being sent only when data needs to be sent out. If the "connection" fails, either because the remote computer has crashed, or because some network link between you and him has failed, there's no "click-dialtooone", like if someone's telephone line failed; it's just that any future packets aren't going to get through. Thus, the sort of pinging that KEEPALIVE does is really the only way to reliably detect a dropped connection.
Quote:Original post by Sneftel
When he says pinging, he doesn't mean an ICMP ping. He means a small injection into the TCP stream which the other side ignores but acknowledges, demonstrating that the TCP connection still works.


Yeah, that's what I meant. TCP/IP keepalives work just as well, of course...
SO_KEEPALIVE does not guarantee that the connection will stay open, but it does allow you to detect a failed connection that would otherwise not be detected. I'm sure it's what you want.

Normally, an idle connection will just sit there with no packets going across, indefinitely. Provided both machines stay online and no intermediate stateful router / firewall / NAT cuts them off, this is fine.

But if one peer unexpectedly disconnects (for example, by having its power turned off), then other won't know that this has happened, as no message will be sent notifying them.

SO_KEEPALIVE occasionally sends messages on these connections to make sure the other end is still there.

So it does what you want.

SO_KEEPALIVE may actually help the session to stay open as well, as stateful routers, firewalls and NAT, will have finite resources and might forget about connections that they think have been idle too long.

Mark

This topic is closed to new replies.

Advertisement