首页 文章

关闭System.Net.Sockets.TcpClient会杀死同一IP地址上其他TCPClient的连接

提问于
浏览
2

为了清楚起见,我在这里提到的所有TCPClient都不是我自己的类的实例,它们都是Mono .NET 4.0实现的System.Net.Sockets.TcpClient的实例 .

我有一台服务器正在监听客户端连接,就像服务器那样 . 每当它获得一个新的客户端时,它就会创建一个新的TCPClient来处理新线程上的连接 . 我用字典跟踪所有连接和线程 . 如果客户端断开连接,它会向服务器发送断开连接消息,TCPClient关闭,字典条目被删除,线程自然死亡 . 没有大惊小怪,没有麻烦 . 服务器可以毫无问题地处理多个客户端 .

但是,我正在模拟如果客户端断开连接,没有机会发送断开连接消息,然后重新连接会发生什么 . 我正在检测客户端是否已重新连接用户名系统(当我完成测试时它会更安全) . 如果我只是创建一个新的TCPClient并让旧的TCPClient保持运行,那么系统工作正常,但是我有一堆无用的线程在占用空间而什么都不做 . 懒虫 .

所以我尝试关闭与旧连接关联的TCPClient . 当我这样做时,新的TCPClient也会死掉,客户端程序会抛出此错误:

E/mono    (12944): Unhandled Exception: System.IO.IOException: Write failure ---> System.Net.Sockets.SocketException: The socket has been shut down

并且服务器抛出此错误:

Unable to write data to the transport connection: An established connection was aborted by the software in your host machine.

Cannot read from a closed TextReader.

因此,使用远程 endpoints 关闭旧TCPClient: 192.168.1.10:50001

同时使用远程 endpoints 打破新的TCPClient: 192.168.1.10:50002

因此,两个TCPClient对象具有相同的远程 endpoints IP地址,但具有不同的远程 endpoints 端口 . 但关闭一个似乎阻止了另一个工作 . 我希望能够关闭旧的TCPClient来进行清理,而无需关闭新的TCPClient .

我怀疑这与TCPClient如何处理低级别的套接字有关,但没有真正理解它,我无法修复它 .

3 回答

  • 3

    我的套接字服务器上有类似的问题 . 我使用简单的List而不是字典来保存我当前的所有连接 . 在一个侦听新流的连续while循环中,我有一个try / catch,如果它已断开连接,它会在catch块中杀死它 .

    在sever.cs上有这样的东西:

    public static void CloseClient(SocketClient whichClient)
            {
                ClientList.Remove(whichClient);
                whichClient.Client.Close();
                // dispose of the client object
                whichClient.Dispose();
                whichClient = null;
            }
    

    然后在客户端上使用一个简单的dispose方法:

    public void Dispose()
            {
                System.GC.SuppressFinalize(this);
            }
    

    EDIT: 此粘贴是他或她在我的代码帮助下自行找到的OPs解析 .

    所以要澄清一下,情况是我有两个TCPClient对象TCPClientA和TCPClientB具有不同的远程 endpoints 端口,但是相同的IP:

    TCPClientA.Client.RemoteEndPoint.ToString();
    

    返回:192.168.1.10:50001

    TCPClientB.Client.RemoteEndPoint.ToString();
    

    返回:192.168.1.10:50002

    TCPClientA需要清理,因为它不再有用,所以我打电话

    TCPClientA.Close();
    

    但由于某种原因,这会关闭TCPClientB另一端的客户端的套接字 . 但是,写作

    TCPClientA.Client.Close();
    TCPClientA.Close();
    

    成功关闭TCPClientA而不干扰TCPClientB . 所以我已经解决了这个问题,但我不明白为什么会这样 .

  • 0

    这听起来像是代码中的错误 . 关闭一个入站连接不应该关闭另一个 .

  • 0

    看起来你找到了一个解决方案但是你知道在.net中编写客户端/服务器应用程序时有许多类似的缺陷 . 有一个开源网络库(完全支持单声道),这些问题已经解决了,networkComms.net . 基本样本是here .

    免责声明:这是一个商业产品,我是创始人 .

相关问题