需要明确的是,我在这里指的所有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.
因此,使用一个远程端点关闭旧的TCPClient,例如:192.168.1.10:50001
还会使用远程端点(例如:192.168.1.10:50002)破坏新的TCPClient.
因此,两个TCPClient对象具有相同的远程端点IP地址,但具有不同的远程端点端口.但是关闭一个似乎阻止了另一个.我希望能够关闭旧的TCPClient进行清理,而不必关闭新的TCPClient.
我怀疑这与TCPClient如何在较低的级别上使用套接字有关,但是对此没有任何真正的了解,我无法修复它.
解决方法:
我的套接字服务器上也有类似的问题.我使用一个简单的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.所以我已经解决了问题,但我不明白为什么会这样工作.