2

我正在尝试断开客户端与服务器的连接,但服务器仍将其视为已连接。我找不到解决方案,关机、断开连接和关闭都不起作用。

我与客户端断开连接并检查服务器的一些代码:

客户:

  private void btnDisconnect_Click(object sender, EventArgs e)
    {
        connTemp.Client.Shutdown(SocketShutdown.Both);
        connTemp.Client.Disconnect(false);
        connTemp.GetStream().Close();
        connTemp.Close();
    }

服务器:

    while (client != null && client.Connected)
            {
                NetworkStream stream = client.GetStream();
                data = null;

                try
                {
                    if (stream.DataAvailable)
                    {
                        data = ReadStringFromClient(client, stream);
                        WriteToConsole("Received Command: " + data);
                    }
                } // So on and so on...

代码中有更多的写入和读取。

希望大家能帮忙。

更新:我什至尝试通过 ref 传递 TCP 客户端,假设存在范围问题并且 client.Connected 即使在读取后仍然为真。出了什么问题?

第二次更新!!:

这是解决方案。窥视一下,并据此确定您是否已连接。

  if (client.Client.Poll(0, SelectMode.SelectRead))
                    {
                        byte[] checkConn = new byte[1];
                        if (client.Client.Receive(checkConn, SocketFlags.Peek) == 0)
                        {
                            throw new IOException();
                        }
                    }
4

4 回答 4

7

这是解决方案!

  if (client.Client.Poll(0, SelectMode.SelectRead))
                {
                    byte[] checkConn = new byte[1];
                    if (client.Client.Receive(checkConn, SocketFlags.Peek) == 0)
                    {
                        throw new IOException();
                    }
                }
于 2010-09-24T16:39:40.213 回答
1

MSDN 文档

Connected 属性获取上次 I/O 操作时客户端套接字的连接状态。

当它返回 false 时,客户端套接字要么从未连接,要么不再连接。因为 Connected 属性仅反映最近操作时的连接状态,所以您应该尝试发送或接收消息以确定当前状态。消息发送失败后,该属性不再返回true。请注意,此行为是设计使然。您无法可靠地测试连接的状态,因为在测试和发送/接收之间的时间内,连接可能已经丢失。您的代码应假定套接字已连接,并优雅地处理失败的传输。

于 2010-09-23T21:00:26.693 回答
1

我不确定 NetworkStream 类,但我认为它的行为类似于 Socket 类,因为它主要是一个包装类。通常,除非客户端对套接字执行 I/O 操作(读取或写入),否则服务器不会意识到客户端与套接字断开连接。但是,当您在套接字上调用 BeginRead 时,直到有数据要从套接字读取时才会调用回调,因此调用 EndRead 并获得字节读取返回结果 0(零)意味着套接字已断开连接。如果您使用 Read 并获得零字节的读取结果,我怀疑您可以检查底层 Socket 类的 Connected 属性,如果客户端由于在套接字上执行 I/O 操作而断开连接,则它将是错误的。

于 2010-09-23T21:21:35.277 回答
0

这是一个一般的 TCP 问题,请参阅:

解决此问题的方法往往依赖于发送作为协议一部分的预期数据量。这就是 HTTP 1.1 使用Content-Length标头(针对整个实体)或使用分块传输编码(具有各种块大小)所做的事情。

另一种方法是定期发送“NOOP”或类似的命令(本质上是什么都不做但确保通信仍然打开的消息)作为协议的一部分。

(你也可以在你的协议中添加一个命令,客户端可以发送给服务器以干净地关闭连接,但没有得到它并不意味着客户端没有断开连接。)

于 2010-09-23T21:15:06.067 回答