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

时间:2012-02-08 01:33:38

标签: c# networking tcpclient robustness

为了清楚起见,我在这里提到的所有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.

所以用一个远程端点:192.168.1.10:50001

关闭旧的TCPClient

还使用例如192.168.1.10:50002

的远程端点中断新的TCPClient

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

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

3 个答案:

答案 0 :(得分: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);
        }

编辑:此粘贴是他或她在我的代码帮助下自行找到的OP分辨率。

所以要澄清一下,情况是我有两个TCPClient对象TCPClientA和TCPClientB具有不同的远程端点端口,但是相同的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。所以我已经解决了这个问题,但我不明白为什么会这样。

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

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