tags:

views:

68

answers:

3

Hi All,

I am using an ElSSLSocket from C#. This is a SecureBlackBox socket. SecureBlackBox is a third party library to handle secure sockets.

I can see that the ElSSLSocket object has a property called 'Socket' so the underlying socket is a normal .NET socket.

My question, is there some kind of event that I can subscribe to so that I can see when the socket disconnects uncleanly? I have a client server connection which often will disconnect. It is hard to see if it is the client or the server, and hard to see the actual cause.

I am pretty sure that there is some logic problems in the application, i.e. this is not caused by network outages or anything like that.

I should also let you know that the disconnections I get are this error,

SocketException - An existing connection was forcibly closed by the remote host

ErrorCode - 10054

If there was any way that I could actually find the cause of that?

+1  A: 

I've found this to work quite well:

Receiving

_socket.Poll(100, SelectMode.SelectRead) && _socket.Available == 0

Sending

!_socket.Poll(100, SelectMode.SelectWrite)
ChaosPandion
OK. Thanks. I did a test, I am doing a 'write' to a socket from the client end, so I disconnected the server end. So am I right to call _socket.Poll(100, SelectMode.SelectWrite)? And should I expect a result of false? The result was true. The thing I did notice though is that the 'Connected' property became false before the next call to 'Send' on the client end. I might try and use that. What do you reckon?
peter
@peter - Don't forget the `!`.
ChaosPandion
Is there a difference between the type of sockets you are using compared to me? I am using blocking sockets. Also when you call 'Poll' what is it actually doing? Checking the remote socket is connected? Or just checking that the local socket is functioning as expected? Perhaps it is slow to react to the disconnection.
peter
You say don't forget the ! I get the same result regardless. I am a bit confused now. If I say,if (!_socket.Poll(100, SelectMode.SelectWrite))Is this showing us that it is working, or not working?
peter
@peter - Can you show a bit of your code? This may not work in certain configurations.
ChaosPandion
OK, not right now though. Tomorrow. There is quite a bit of code, so I will have to move it around and make it readable.
peter
+2  A: 

Detecting half-open connections is one of the classic socket programming scenarios. The Socket.Connected property is completely useless, and Socket.Poll does not work for every situation. It's best to actually send a "heartbeat" message every few seconds.

10054 is one of the common errors. It means the connection has been lost (not cleanly closed). It can be caused by the remote computer shutting down, the remote process exiting, or even an intermediate router being rebooted.

Stephen Cleary
This is the only way to do it. I spent several months working with sockets and this is the conclusion. Alternatively, you can just use WCF which will make all your problems go away.
SLC
@SLC - I would not exactly call WCF a panacea. Sometimes you want the simplicity Sockets over framework bloat.
ChaosPandion
I guess where I want to get to is to know which disconnects first, the client or the server. The socket connection could actually be going out of scope, i.e. a program error occurs which is not reported, but causes an exception to bubble up the stack. Kind of hard to explain.
peter
The more I think about it the more I speculate that this error is more than likely not serious. The process involves syncing data between client and server which can be very slow. The likely cause is that the 'users' are going 'this is slow, stuff this', and cancelling the process. The sync process can handle this and keeps going if they restart it. Also as I mentioned before if a particular exception occurs in the code it might not be closing the sockets cleanly either.
peter
So another point, how should the socket be closed? If one end closes cleanly I am guessing the 'connected' property is set to false on the other end?
peter
The socket can be closed by just calling `Close`. It won't raise any normal exceptions, so this should be done every time a read or write operation fails. I don't know about the affect on the `Connected` property; this property was a design mistake to begin with and everyone with experience in native sockets (including me) just ignores it.
Stephen Cleary
+2  A: 

While this is written in C, you should be able to do the same thing in C#:

int dummy;
// since you're just testing if the socket is still open for reading you don't
// want it to block, or remove data from the sockets recv buffer
int ret = recv(sockfd, &dummy, sizeof dummy, MSG_DONTWAIT | MSG_PEEK);

if ( ( ret == -1 && ( errno == EAGAIN || errno == EWOULDBLOCK ) )
      || ret > 0 ) {

    // socket is still open for reading

else if ( ret == 0 ) { 

    // socket went through orderly shutdown and is closed for reading

} else {

    // there is some error and the socket is likely closed
    // check errno

}

Let's say you think it's half closed and you still have data you want to write.

int myData = 0xDEADBEEF;
int ret = send(sockfd, myData, sizeof myData, MSG_NOSIGNAL);

This way, if the socket is completely closed your send won't kill your program with a SIGPIPE. Instead the call will just return -1 and set errno to EPIPE.

Robert S. Barnes