当socket关闭时,TcpClient.EndConnect抛出NullReferenceException

时间:2011-07-19 21:45:32

标签: c# sockets asynchronous connection tcpclient

我正在尝试使用TcpClient.BeginConnect / TcpClient.EndConnect组合连接到我的服务器。但是,有些事情不能正常运作。

方案如下:

  • 致电TcpClient.BeginConnect
  • 服务器故意脱机(用于测试目的) - 因此无法建立连接。
  • 我关闭了应用程序(在closes the socket which in turn stops the async operation
  • 的过程中调用client.Close()
  • TcpClient连接回调方法正在执行IAsyncResult
  • 使用给定的TcpClient.EndConnect
  • 调用IAsyncResult方法
  • NullReferenceException发生在EndConnect
  • 由于上一个表单(窗口)已关闭,应用程序应该退出 - 但它不会,至少在BeginConnect操作完成之前(这很奇怪,因为已经调用了回调)。

exception

这里发生的事情是NullReferenceException被抓住了。从上图中可以看出,clientar都不是null。问题是MSDN documentation for the EndConnect没有提到抛出此异常的情况。

所以基本上,我不知道发生了什么。问题是我被迫等待应用程序关闭(好像连接操作仍然等待超时)。 如果服务器在线,它会连接并断开连接

在此上下文中 NullReferenceException 意味着什么?如果无法建立连接,如何避免BeginConnect操作阻止应用程序关闭?


附加说明在评论中要求):

以下是创建客户端的代码(客户端是成员变量:

public void Connect()
{
    try
    {
        lock (connectionAccess)
        {
            if (State.IsConnectable())
            {
                // Create a client
                client = new TcpClient();
                client.LingerState = new LingerOption(false, 0);
                client.NoDelay = true;

                State = CommunicationState.Connecting;

                client.BeginConnect(address, port, onTcpClientConnectionEstablished, null);
            }
            else
            {
                // Ignore connecting request if a connection is in a state that is not connectable 
            }
        }
    }
    catch
    {
        Close(true);
    }
}

还有Close方法:

public void Close(bool causedByError)
{
    lock (connectionAccess)
    {
        // Close the stream
        if (clientStream != null)
            clientStream.Close();

        // Close the gateway
        if (client != null)
            client.Close();

        // Empty the mailboxes
        incomingMailbox.Clear();
        outgoingMailbox.Clear();

        State = causedByError ? CommunicationState.CommunicationError : CommunicationState.Disconnected;
    }
}

4 个答案:

答案 0 :(得分:1)

NullReferenceException可能是由于TcpClient.Client为空。

如果您要关注TcpClient.BeginConnect TcpClient并将 private void onConnEst(IAsyncResult ar) { try { TcpClient client = (TcpClient)ar.AsyncState; if(client!=null && client.Client!=null) { client.EndConnect(ar); } } catch(Exception ex){...} } 对象作为状态对象传递:

Close()

这应该处理在回调之前调用{{1}}的情况。

回到你的问题 - 应用程序最终关闭需要多长时间?

答案 1 :(得分:1)

这显然是TcpClient类中的一个错误。我也面对过它。 TcpClient.Dispose可以将Client字段设置为null,但EndConnect不期望这样。

答案 2 :(得分:0)

我遇到了类似的错误,最后使用了这段代码。我不确定它是否适用于IASyncResult接口,但可能有类似的方法来运行此检查。我注意到你的ar.AsyncState == null,所以也许尝试从那里开始,即正确连接时它是否为null?

private void connConnectCompleted(AsyncCompletedEventArgs e)
{
    if (e.Error != null)
    {
        // Something didn't work...abort captain
        CloseSocket();
        Console.WriteLine(this.GetType().ToString() + @":Error connecting socket:" +  e.Error.Message);
        return;
    }
    // Do stuff with your connection
}
编辑:对不起,我没有意识到我没有发布生成我的AsyncCompletedEventArgs的内容,这与你正在做的事情有关。您将看到我想知道ar.AsyncState为空的原因。

private void OnConnect(IAsyncResult asyncResult)
{
    if (OnConnectCompleted == null) return; // Check whether something is using this wrapper
    AsyncCompletedEventArgs args;
    try
    {
        Socket outSocket = (Socket) asyncResult.AsyncState;

        // Complete connection
        outSocket.EndConnect(asyncResult);

        args = new AsyncCompletedEventArgs(null);
        OnConnectCompleted(this, args);
    }
    catch (Exception e)
    {
        args = new AsyncCompletedEventArgs(e.Message);
        OnConnectCompleted(this, args);
    }
}

答案 3 :(得分:0)

这是a know bug

您应该收到'ObjectDisposedException'而不是'NullReferenceException'。