Alchemy-Websockets - WebSocketClient抛出NullReferenceException异常

6
我有两个C#程序,应该通过WebSockets通信。服务器完美地工作(也使用Alchemy),已经有一段时间了(使用javascript客户端)。然而,连接一个Alchemy WebSocketClient会在客户端上抛出NullReferenceException异常。在进行一些调试后,我发现异常是在WebSocketClient.cs的第187行抛出的,因为调用了_context.Connection.Connected。_context.Connection与本地的_client是同一个实例,在那个时刻都不为null。在msdn.microsoft.com的TcpClient.Connected页面上没有列出任何可能的异常(这表明它不应该抛出任何异常)。更进一步,我注意到_client类变量在WebSocketClient.cs的第176行被改变,从一个正常的实例变成一个充满异常的实例:

第176行之前 第176行之前

第176行之后 第176行之后

就在这一行之后,刚刚添加到第187行的Context的Dispose()方法被调用,断开了Connection(它是与我之前在第131行提到的_client相同的实例,在Context.cs中)。

我的问题是:为什么会发生这种情况,如何阻止它发生并成功连接所需的WebSocketServer?

如果您需要更多信息,请不要犹豫在评论中向我提问。

编辑1

只有当服务器实际在监听时,异常才会发生。如果服务器处于非活动状态,则不会到达WebSocketClient.cs的第176行(这是正确的行为,因为当与服务器建立连接时会调用OnRunClient())。 编辑2 如请求的堆栈跟踪:
System.NullReferenceException was unhandled
  HResult=-2147467261
  Message=Object reference not set to an instance of an object.
  Source=System
  StackTrace:
       at System.Net.Sockets.TcpClient.get_Connected()
       at Alchemy.WebSocketClient.SetupContext(Context context) in C:\...\Alchemy\WebSocketClient.cs:regel 187
       at Alchemy.WebSocketClient.HandleClientThread() in C:\...\Alchemy\WebSocketClient.cs:regel 94
       at System.Threading.ThreadHelper.ThreadStart_Context(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.Threading.ThreadHelper.ThreadStart()
  InnerException:

在错误发生前,请贴出代码。 - Florian
所有的内容都在WebSocketClient.cs和Context.cs文件中(这些文件的提及在上面的问题中是链接)。我没有改变这些文件的任何方式。 - Manuel
1个回答

2
我看到你使用了TcpClient。这个类使用Socket类进行数据传输(TcpClient有这样的字段)。据我所知,在某些情况下,这个字段可能为null。 TcpClient的Connected属性使用内部Socket实例的Connected属性。大概是这样的:
public bool Connected 
{
    get 
    {
         return _socket.Connected; // Possible NullRef here!!!
    }
} 

当此字段为空时,您将收到 NullReferenceException 异常。据我所知,这可能是在连接未成功建立时发生的。
例如,在您的代码中我看到了这个:
try
{
     _client.EndConnect(result);
}
catch (Exception ex)
{
     Disconnect();
     connectError = true;
}

using (_context = new Context(null, _client))
{
      _context = new Context(null, _client);
      _context.BufferSize = 512;
      // some code
}

如果连接出现问题,您将收到一个异常并进行一些操作,但在这种情况下,您的“_client”将未初始化套接字字段。在“Context”构造函数中,您将尝试使用它字段(在“Connected”属性中),然后会收到NullReferenceException异常。
我猜您需要在catch块中添加返回语句。
或者,检查TcpClient的底层属性Client(http://msdn.microsoft.com/ru-ru/library/system.net.sockets.tcpclient.client(v=vs.110).aspx),像这样:
if (_client.Client != null && _client.Connected)
{
    // do what you need
}

希望这能对你有所帮助。

我知道如何检查客户端是否连接/为空,我需要知道的是如何完全阻止这种情况发生。 - Manuel
@dragon112 抱歉,我现在不理解你的意思。我提到了两个弱点。第一个是 TcpClient 写了一些“特定”的代码(反编译器也同意我的观点),我们无法对其进行任何更改,只能使用变通方法。第二个是您创建了 Context,无论连接是否成功(为什么?),这很奇怪,但您可以修复它。 - Tony
哦,我明白了。我再看了一遍代码,发现有些部分很薄弱。这些类肯定需要修复。这就是我能说的了。 - Tony

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接