1

为了清楚起见,我在这里提到的所有 TCPClients 都不是我自己的类的实例,它们都是来自 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

还使用远程端点打破新的 TCPClient 说:192.168.1.10:50002

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

我怀疑这与 TCPClient 如何在低级别使用套接字有关,但对此没有任何真正的了解,我无法修复它。

4

3 回答 3

1

我的套接字服务器上有类似的问题。我使用一个简单的列表而不是字典来保存我当前的所有连接。在侦听新流的连续 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);
        }

编辑:这个粘贴是他或她在我的代码的帮助下自己找到的 OPs 解决方案。

所以澄清一下,情况是我有两个 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();

在不干扰 TCPClientB 的情况下成功关闭 TCPClientA。所以我已经解决了这个问题,但我不明白为什么它会这样工作。

于 2012-02-08T01:58:20.757 回答
-2

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

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

于 2012-02-10T12:30:52.220 回答
-2

这显然是您的代码中的错误。仅仅关闭一个入站连接不可能关闭另一个。显然,您的代码中的其他地方正在发生其他事情。

于 2012-02-08T09:27:17.463 回答