为了清楚起见,我在这里提到的所有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
还使用例如192.168.1.10:50002
因此,两个TCPClient对象具有相同的远程端点IP地址,但具有不同的远程端点端口。但关闭一个似乎阻止了另一个工作。我希望能够关闭旧的TCPClient来进行清理,而无需关闭新的TCPClient。
我怀疑这与TCPClient如何处理低级别的套接字有关,但没有真正理解它,我无法修复它。
答案 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。
免责声明:这是商业产品,我是创始人。