简体   繁体   English

TCP 插座连接

[英]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.我有一个 windows 服务,除其他外,它使用 .NET System.Net.Sockets 库监听来自远程设备的传入数据。 The example below only has one remote device pushing data every 60 seconds.下面的示例只有一个远程设备每 60 秒推送一次数据。

Every so often, this service will stop and a message (shown below) will appear in the windows logs of the server.每隔一段时间,该服务就会停止并且一条消息(如下所示)会出现在服务器的 windows 日志中。

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).将此事件的时间与我上次的日志语句匹配后,我发现当远程设备在短时间内两次连接到服务时会发生此致命异常(通常,它每 60 秒连接一次以推送数据)。 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 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 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...我在ReceiveCallback function 中添加了更多日志记录和异常处理,今天早上在我的日志文件中发现了以下内容......

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.因此,关键是(如上面的一些答案中突出显示的那样)捕获ReceiveCallback function 中的异常,并确定它们是否严重到足以杀死您的应用程序。

If your code follows the sample quite closely then you should really have a try-catch around:如果您的代码非常接近示例,那么您应该真的有一个 try-catch :

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.ReceiveCallback function 中,因为它可能就像您尝试接收时关闭套接字连接一样简单。

Rather than killing the process you can probably just continue.而不是终止进程,您可能可以继续。

You should always catch (Exception err) in all callback methods.您应该始终在所有回调方法中catch (Exception err) 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.当然,您可能会遇到像OutOfMemoryException这样应该终止您的应用程序的致命异常。 But in most cases it's unlikely.但在大多数情况下,这不太可能。

The first thing I would do is check the value of the ErrorCode property in the thrown SocketException .我要做的第一件事是检查抛出的SocketExceptionErrorCode属性的值。 Look-up this value in the winsock error code list for some pointers to what might be going wrong.winsock 错误代码列表中查找此值,以获取一些指向可能出错的指针。

If you post the error code then I might be able to help further.如果您发布错误代码,那么我可能会提供进一步的帮助。

EndAccept can and does throw exceptions when a client connections fail to transition from half open to fully open states.当客户端连接无法从半开状态转换到全开状态时,EndAccept 可以并且确实会引发异常。 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.另请注意,它会在侦听器关闭后抛出ObjectDisposedException ,因此您必须实际查看异常并根据出现的问题确定要做什么。

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. EndReceive通常在客户端连接被强制关闭时抛出,但是您必须再次查看异常并根据抛出的异常确定要做什么。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM