views:

73

answers:

1

I have a C# app where a server and some clients communicate from different machines using sockets.

Most of the time, the server detects a dis-connect correctly when it receives 0 bytes in the sock.Receive(...) call. But when there is a hardware issue (say a network cable is unplugged), there is a problem. One server thread continues to block on sock.Receive(...) because it doesn't know the connection is lost. I was going to add a heartbeat message to detect this, but I wanted to test it in dev.

But I'm not sure how I can test this case without an actual hardware issue. Even when I just kill the client process, the socket somehow manages to dis-connect gracefully (that is, the server does a read of 0 bytes). It's only when I physically unplug the client machine from the network that I see this issue.

Is there any way that I can simulate this issue in dev?

+1  A: 

You need to explicitly inform WinSock that you don't want it to clean up for you after closing the socket. This is done by setting LingerState as such:

socket.LingerState = new LingerOption(true, 0);
socket.Close();

LingerState is a bit confusing, because if you disable the linger, WinSock will actually linger but just not block your program. You have to enable the linger and set the linger timeout to zero in order to force WinSock to drop the connection.

P.S. If you want some info about keepalive packets (heartbeats), I've written a blog entry on the subject.

Update:

I re-read your question (and comment), and my answer is wrong...

The code above will simulate an abortive close, not a half-open situation. There isn't a way to simulate a half-open situation in software; you need to unplug an Ethernet cable that is not attached to either computer in order to test this (e.g., yank the cable between the two switches in this configuration: computer A <-> switch <-> switch <-> computer B).

Stephen Cleary
That is a great post, thanks! I usually end up doing something like (2) Add a keepalive message to the actual application protocol (a "null" message).But is there really no way to simulate such a half-open socket for testing? It's going to be a real pain to physically unplug the cables. But I guess it only have to be done a few times.
Michael Covelli
@Michael: I'm not aware of any way to test this in software. If you had a third switch, then you could toggle power on it, which may be easier (and, for many switches, possible to do in software). But data would have to timeout during the time it's powered off to be a valid test. There's no setting I'm aware of that would enable this kind of test just using the OS.
Stephen Cleary
Stephen Cleary
This post http://stackoverflow.com/questions/776396/how-can-i-simulate-a-socket-disconnection-on-windows-between-a-client-and-a-ser claims that you can do it with TCPView. It also suggests using VirtualBox.com to simulate another computer (its free).
Michael Covelli
@Michael: Forcing a socket closed with TCPView would have the same result as abortively closing it in code (the other side gets a RST response from the OS the next time it sends a packet because the port is already closed; in a half-open situation, the other side's packets need to time out instead). VirtualBox does sound like it may work, though!
Stephen Cleary