【问题标题】:TcpClient.Close doesn't close the connectionTcpClient.Close 不会关闭连接
【发布时间】:2011-02-02 20:11:07
【问题描述】:

我有一个使用 TcpClient 和 TcpListener 通过网络进行通信的应用程序。但是,当我在客户端上调用 TcpClient.Close 将其与服务器断开连接时,服务器根本没有反应。

现在,在您发表评论说这个问题与this 重复,以及如何找到解决方案here 之前,请相信我,当我说我已经找到并尝试了这些问题时。它没有帮助。我还尝试了TcpClient.CloseTcpClient.GetStream().Close()TcpClient.Dispose 的不同组合。没有任何效果。

代码没有什么值得注意的,只是客户端中的一个 Disconnect 方法,它重置所有变量以供重用,并关闭所有网络资源。服务器有一个循环,检查TcpClient.Connected是否为真,如果为假,则应该跳出循环并终止线程。

有什么想法吗?

【问题讨论】:

    标签: c# networking tcpclient


    【解决方案1】:

    TcpClient.Connected 几乎应该被忽略。它基本上代表了最后一次通信是否成功。来自MSDN(强调我的):

    由于 Connected 属性仅反映最近操作时的连接状态,因此您应该尝试发送或接收消息以确定当前状态。消息发送失败后,该属性不再返回true。请注意,此行为是设计使然。您无法可靠地测试连接的状态,因为在测试和发送/接收之间的时间内,连接可能已经丢失。 您的代码应假定套接字已连接,并优雅地处理失败的传输。

    如果您在客户端调用Close(),则不会向服务器发送任何内容来告诉它它正在关闭,它实际上只是自行关闭它,这样客户端就不能再使用它了。确定您是否仍然连接的唯一可靠方法是尝试发送数据并处理故障。如果您愿意,您可以实现自己的握手协议,当您调用 Close() 时,您会向服务器发送一个特殊通知,提醒它注意这一事实,但仍有一些时候该数据包永远不会到达服务器。

    【讨论】:

    • 非常感谢!我所要做的就是向服务器发送一条断开连接的消息。我想我可以通过调用方法并让套接字自己解决这个问题来做到这一点,但我想生活并不那么容易。
    • @Bevin,只要确保服务器也处理没有机会发送断开消息的断开连接。
    • 实际上,没有任何东西发送到服务器告诉它正在关闭的声明对于 TCP 连接来说是不正确的。当 TCP 连接正常终止时,希望发起连接终止的一方会发送一条设置了 FIN 标志的消息。不幸的是,NetworkStream 或 TcpClient 类似乎没有任何方法可以检测到这种情况已经发生,即使底层套接字 API 可以。所以,实际上,克里斯的回答是解决问题的正确方法。
    【解决方案2】:

    侦听一个字节,如果收到,则获取其余的。 如果接收一个字节返回0,则客户端断开连接。

            IPAddress nReceiveAddress = IPAddress.Parse(GetIp(sSource));
            IPEndPoint localEndPoint = new IPEndPoint(nReceiveAddress, GetPort(sSource));
            Socket nSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            nSocket.Bind(localEndPoint);
    
            nSocket.Listen(10);
            Socket nSocketClient = nSocket.Accept();
    
                    byte[] bufferOne = new byte[1];
                    int nBytes = nClient.Receive(bufferOne);
    
                    if (nBytes == 0)
                    {
                        AppendToLog(String.Format("{0}: Closing.", sName));
                        nClient.Close();
                    }
                    else
                    {
                        byte[] buffer = null;
                        buffer = new byte[nClient.Available + 1];
    
                        if (nClient.Available > 0)
                            nBytes = nClient.Receive(buffer);
    
                        if(nBytes>0)
                        {
                            //KS effectively insert the first received byte at start.
                            Array.Copy(buffer, 0, buffer, 1, buffer.Length - 1);
                            buffer[0] = bufferOne[0];
                        }
                    }
    

    【讨论】:

      猜你喜欢
      • 2019-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-15
      • 1970-01-01
      • 1970-01-01
      • 2014-12-05
      • 1970-01-01
      相关资源
      最近更新 更多