Skip to main content
GameDev.net gamedev.net
🔒 Locked

Detecting dead TCP socket

Started by DrjonesDW3d Jan 30, 2006 at 11:06 PM 2 replies 5.9k views
Original Post
DrjonesDW3d
DrjonesDW3d
Using windows socket code, is there any way to detect a dead socket in a proactive way? You can always do the if(socket times out on write) { socket dead } This only works when you have to write. You can't detect a dead socket if you are reading, unless you know you are suposed to read data. I know you can also use the keepalive option, but that only works if the server supports it (server in one case is a microcontroller, which doesn't). Is there any other way to do this without doing a write? Can you send like a zero length packet and get back an ACK and tell that way? Is there some obscure function for windows sockets that lets you do this? Or do I have to hack some kind of pseudo keep alive using an echo type packet that is sent every time period I'm interested in? Current problem I am having is that if a socket is dead due to the server reseting or the physical connection being severed (which can happen due to outside circumstances) it takes a couple of writes to detect that things aren't working. The really bad part about this, is that different systems seem to require a different number of writes. Anyone got any ideas?
markr
markr
Quote:
Original post by DrjonesDW3d
Using windows socket code, is there any way to detect a dead socket in a proactive way?


TCP or UDP? TCP I assume (from reading the above).

You can use SO_KEEPALIVE.

Quote:

if(socket times out on write) {
socket dead
}


Technically any error on a TCP socket indicates that it is no longer useful. TCP sockets are entirely reliable during their useful lifetime, and once a proper error happens, they become dead. Once dead, any read/write attempt will lead to an error being flagged immediately; you should close the socket.

Quote:

This only works when you have to write. You can't detect a dead socket if you are reading, unless you know you are suposed to read data.


If the underlying TCP stack knows the socket is dead, it will notify the application when it tries to read. This includes using select()

Quote:

I know you can also use the keepalive option,


You mean SO_KEEPALIVE

Quote:

but that only works if the server supports it (server in one case is a microcontroller, which doesn't).


Ahh. If there's no SO_KEEPALIVE on the other end, you should write your own "do nothing" messages periodically into the socket to keep the connection open and detect if the peer has gone away.

Quote:

Is there any other way to do this without doing a write?


I don't think so.

Quote:

Can you send like a zero length packet...


If you're using TCP, you cannot send a PACKET AT ALL. TCP is stream based. You can't send a packet using TCP. TCP deals with bytes, not packets.

You can send a zero-length MESSAGE using your protocol - this of course, would still have a message length / type, hence would contain some actual data.

Quote:

and get back an ACK and tell that way? Is there some obscure function for windows sockets that lets you do this?


No. Add a NOP message to your protocol which is ignored, and use that. If the peer has died, not only will you not get a response, but the socket will fail (after a tiemout period) with ECONNRESET or ETIMEOUT or something.

Quote:

Current problem I am having is that if a socket is dead due to the server reseting or the physical connection being severed (which can happen due to outside circumstances) it takes a couple of writes to detect that things aren't working. The really bad part about this, is that different systems seem to require a different number of writes.


Because you're using TCP, it's necessary to allow time for the OS to retry before it can assume that the peer is dead. TCP has a built in retry mechanism and won't announce that the socket is broken just because a single packet has been lost.

It waits between retry attempts (because it doesn't know that the packet was lost yet) and retries many times typically.

Some operating systems allow you to tune the retry options either globally or per-socket. I don't know whether Windows is one of them.

Mark
Telastyn
Telastyn
Quote:

You can't detect a dead socket if you are reading, unless you know you are suposed to read data.


Oh? (assuming TCP)

If you're using select(), then you do. select() will return the dead socket ready for read if it is broken, and the subsiquent recv() call will return 0 or -1 if it's dead. IIRC 0 means a clean client disconnect, and -1 means something broke the connection.
Bregma
Bregma
Depends on what you mean by 'dead.'

A shut socket can be detected by using a select() with timeout of zero. It will return a read-available, and the subsequent read will fail with a socket-closed indicator.

There is no way to tell if a socket has been disconnected without being shut down. TCP is specifically designed that way. You can set up a TCP connection then physically disconnect it and leave it that way for, say hours (months, if you're running Linux), then plug in again and your program will be none the wiser.

Nope, all you can do is try a write (which might fail) or a read with a timeout (which might time out). It's completely by design.

Stephen M. Webb
Professional Free Software Developer

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.