【问题标题】:TcpClient still connected after server closed connection. Why?服务器关闭连接后,TcpClient 仍然连接。为什么?
【发布时间】:2015-05-22 19:51:46
【问题描述】:

我有一个运行 TCP 客户端的 TCP 服务器——我知道,这太疯狂了。现在我有一个我不清楚的行为,也许有人可以帮助我理解它。

[Test]
[TestCase(2, 1)] // first scenario: Okay!
[TestCase(1, 1)] // second scenario: Huh?
public void NotifyClientAboutError(int clientSendBytes, int serverReadBytes)
{
    var server = new TcpListener(IPAddress.Any, 12345);
    server.Start();

    Task.Factory.StartNew(() =>
    {
        using (var serverClient = server.AcceptTcpClient())
        {
            using (var serverClientStream = serverClient.GetStream())
            {
                for (var i = 0; i < serverReadBytes; i++)
                {
                    serverClientStream.ReadByte();
                }
                serverClientStream.Close();
            }
            serverClient.Close();
        }
    });

    using (var client = new TcpClient())
    {
        client.Connect(IPAddress.Loopback, 12345);
        using (var clientStream = client.GetStream())
        {
            for (var i = 0; i < clientSendBytes; i++)
            {
                clientStream.Write(new byte[] { 42 }, 0, 1);
            }

            // returns 0 - would have expected an Exception here
            clientStream.ReadByte();

            // says: true
            Console.WriteLine(client.Connected);

            // no exception
            clientStream.Write(new byte[] { 42 }, 0, 1);
            clientStream.Flush();

            // says: true
            Console.WriteLine(client.Connected);
        }
    }

    server.Stop();
}

查看包含在 NUnit 测试用例中的两个场景:

首先:服务器读取的字节数少于客户端发送的字节数,然后通过在流上调用Close() 来关闭连接,下面对ReadByte() 的调用失败但有异常。到目前为止,一切都很好。这正是我所期望的。

第二次:服务器读取客户端发送的所有字节,然后关闭连接,下面对ReadByte()的调用不会失败。它返回 0 并且 - 更奇怪的是 - 它表示仍然连接并且客户端仍然可以毫无例外地在流上写入数据。

有人能解释一下为什么第二种情况会这样吗?或者我该如何管理它,在这种情况下获得异常?

【问题讨论】:

    标签: c# tcp connection tcpclient


    【解决方案1】:

    read 如果对等端通过在其末端执行close 发送了 FIN,则返回零。

    read 引发来自对等方的 RST 异常 (ECONNRESET)。

    现在:

    如果recv Q 不为空,实体将发送RST 并尝试close。连接永远消失了。

    如果recv Q 为空,如果尝试close,则FIN 熄灭。这并不意味着另一端不能写入套接字。它还没有调用close。连接是半开的。因此,您观察到客户端能够写入套接字。

    【讨论】:

    • 到目前为止,谢谢,这有点清楚了。现在,这意味着空队列上的 RST 有点毫无意义,而来自 Read0 相当于 >No one is Listening on the remote side。别说话了。?或者有没有这种情况会发生?
    • 0 on read 并不意味着没有人在远程侧收听。这只是意味着远程端发送数据完成。这并不意味着也停止与我交谈。
    猜你喜欢
    • 2012-02-20
    • 2020-06-19
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 2019-04-24
    • 2014-08-05
    • 1970-01-01
    • 2022-01-15
    相关资源
    最近更新 更多