ObjectDisposedException SslStream和TcpClient

时间:2018-11-01 17:33:38

标签: c# .net sockets

我正在将TcpClient与SslStream一起使用。一般而言,一切正常,但偶尔会收到崩溃日志。它似乎来自不稳定的网络连接,但不幸的是,尽管尝试创建“意外情况”,我还是无法在本地复制它:

  • 使用Fiddler复制非常慢的网络连接
  • 在发送数据时杀死服务器应用程序
  • 断开网络电缆的连接

情况是这样的:

我这样称呼BeginRead:

_tcpClientStream.BeginRead(receiveBuffer, 0, receiveBuffer.Length, pfnCallBack, null);

然后像这样调用EndRead:

iRx = _tcpClientStream.EndRead(asyn);

使用iRx的唯一地方是将接收到的数据复制到新数组中:

var bytes = new byte[iRx];
Array.Copy(receiveBuffer, bytes, iRx);

在OnDataReceived回调函数中,我在SslStream上调用EndRead,它引发了一个已处理的异常:

Error in OnDataReceived System.IO.IOException: The read operation failed, see inner exception. ---> System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: size
   at System.Net.Sockets.NetworkStream.BeginRead(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state)
   at System.Net.FixedSizeReader.StartReading()
   at System.Net.FixedSizeReader.ReadCallback(IAsyncResult transportResult)
   --- End of inner exception stack trace ---
   at System.Net.Security._SslStream.EndRead(IAsyncResult asyncResult)
   at System.Net.Security.SslStream.EndRead(IAsyncResult asyncResult)
   at XXXXXXX.OnDataRecevied(IAsyncResult asyn)

通常这不是问题-捕获到此异常,并关闭TcpClient并重新启动以尝试重新连接。

但是,在这种情况下,会抛出第二个异常,该异常来自其中一个UnhandledException错误处理程序:

AppDomain.CurrentDomain.UnhandledException
Current.DispatcherUnhandledException
Current.Dispatcher.UnhandledException
TaskScheduler.UnobservedTaskException

此堆栈跟踪如下:

System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Net.Sockets.NetworkStream'.
   at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)
   at System.Net.FixedSizeReader.ReadCallback(IAsyncResult transportResult)
   at System.Net.LazyAsyncResult.Complete(IntPtr userToken)
   at System.Net.ContextAwareResult.CompleteCallback(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Net.ContextAwareResult.Complete(IntPtr userToken)
   at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
   at System.Net.Sockets.BaseOverlappedAsyncResult.CompletionPortCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
   at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)

我们对这种类型的未处理错误的处理方法是向用户显示一条致命错误,该软件必须关闭。

我的问题是:

  1. 以前有没有人见过此错误,并且能够重现我得到的超出范围的异常?尽管我尝试使用上述方法重新创建问题,但我仍然无法重新创建异常,它始终是更标准的Socket IO异常:

    Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
       at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult)
       at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)
       --- End of inner exception stack trace ---
       at System.Net.Security._SslStream.EndRead(IAsyncResult asyncResult)
       at System.Net.Security.SslStream.EndRead(IAsyncResult asyncResult)
       at XXXXXXXXX.OnDataRecevied(IAsyncResult asyn)
    
  2. 有什么办法可以在我的Socket代码中处理此异常,还是总是出现在这些UnhandledException事件之一中?如果是这样,处理此问题的最佳做法是什么?基本上,我需要事件处理程序中的一些逻辑来识别如果收到此特定错误,则不应关闭软件?

0 个答案:

没有答案