开发者

TCP Socket Connections

I have a windows service which, amongst other things, listens for incoming data from a remote device using the .NET System.Net.Sockets library. The example below only has one remote device pushing data every 60 seconds.

Every so often, this service will stop and a message (shown below) will appear in the windows logs of the server.

The process was terminated due to an unhandled exception. 
   Exception Info: System.Net.Sockets.SocketException Stack: 
   at System.Net.Sockets.Socket.EndReceive(System.IAsyncResult) 
   at Uk.Co.RCID.MoteServer.Server.SocketListener.ReceiveCallback(System.IAsyncResult) 
   at System.Net.LazyAsyncResult.Complete(IntPtr)
   at System.Net.ContextAwareResult.CompleteCallback(System.Object) 
   at System.Threading.ExecutionContext.runTryCode(System.Object) 
   at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode, CleanupCode, System.Object) 
   at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) 
   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) 
   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) 
   at System.Net.ContextAwareResult.Complete(IntPtr) at System.Net.LazyAsyncResult.ProtectedInvokeCallback(System.Object, IntPtr) 
   at System.Net.Sockets.BaseOverlappedAsyncResult.CompletionPortCallback(UInt32, UInt32, System.Threading.NativeOverlapped*) 
   at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32, UInt32, System.Threading.NativeOverlapped*)  

Having matched the timing of this event up with my last log statement, I have discovered that this fatal exception occurs when the remote device connects to the service twice in a short space of time (typically, it connects every 60 seconds to push data). Here is my last log statement before the system crashes.

2011-05-20 13:39:19,545 [6] INFO  Uk.Co.RCID.MoteServer.Server.SocketListener [(null)] - Waiting for a connection...
2011-05-20 13:39:19,545 [10] INFO  Uk.Co.RCID.MoteServer.Server.SocketListener [(null)] - Connection established on [10.64.128.60:11000]
2011-05-20 13:40:20,982 [6] INFO  Uk.Co.RCID.MoteServer.Server.SocketListener [(null)] - Waiting for a connection...
2011-05-20 开发者_JS百科13:40:20,982 [5] INFO  Uk.Co.RCID.MoteServer.Server.SocketListener [(null)] - Connection established on [10.64.128.60:11000]

Without wanting to publish the source code (I can arrange if required, but will need to remove certain details), the socket listening code is based on this example.

http://msdn.microsoft.com/en-us/library/5w7b7x5f.aspx

Any help is greatly appreciated.


Hi Everyone,

Thanks for you responses.

I added more logging and exception handling in the ReceiveCallback function and found the following in my log file this morning...

2011-05-25 04:52:26,816 [5] INFO  Uk.Co.RCID.MoteServer.Server.SocketListener [(null)] - Waiting for a connection...
2011-05-25 04:52:26,816 [10] INFO  Uk.Co.RCID.MoteServer.Server.SocketListener     [(null)] - Connection established on [10.64.128.60:11000]
2011-05-25 04:53:26,841 [10] WARN  Uk.Co.RCID.MoteServer.Server.SocketListener [(null)] - SocketException thrown in ReceiveCallback
2011-05-25 04:53:26,841 [10] WARN  Uk.Co.RCID.MoteServer.Server.SocketListener [(null)] - ErrorCode: [10054]
2011-05-25 04:53:26,841 [10] WARN  Uk.Co.RCID.MoteServer.Server.SocketListener [(null)] - System.Net.Sockets.SocketException (0x80004005): An existing connection was forcibly closed by the remote host at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult) at Uk.Co.RCID.MoteServer.Server.SocketListener.ReceiveCallback(IAsyncResult ar)

So, the key is (as highlighted in some of the answers above) to catch the exceptions inside the ReceiveCallback function and decide if they are severe enough to kill your application.


If your code follows the sample quite closely then you should really have a try-catch around:

int read = handler.EndReceive(ar);

in the ReceiveCallback function because it could be something as simple as the socket connection getting closed while you're trying to receive.

Rather than killing the process you can probably just continue.


You should always catch (Exception err) in all callback methods. DO log the exception.

The reason is that all unhandled exceptions thrown in any other thread than the main thread will terminate your application.

You should treat any exception in the socket callbacks as if the client has disconnected. You could of course get fatal exceptions like OutOfMemoryException that should terminate your application. But in most cases it's unlikely.


EndAccept can and does throw exceptions when a client connections fail to transition from half open to fully open states. Also note that it will throw an ObjectDisposedException after the listener is shutdown so you have to actually look at the exception and make a determination of what to do based on what went wrong.

EndReceive typically throws when the client connection closed forcibly, but again you have to look at the exception and make a determination of what to do based on what exception was thrown.


The first thing I would do is check the value of the ErrorCode property in the thrown SocketException. Look-up this value in the winsock error code list for some pointers to what might be going wrong.

If you post the error code then I might be able to help further.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜