服务器关闭连接后,TcpClient仍然连接.为什么

本文关键字:连接 为什么 TcpClient 服务器 | 更新日期: 2023-09-27 17:50:32

我有一个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,更奇怪的是,它表示仍然连接,客户端仍然可以毫无例外地在流上写数据。

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

服务器关闭连接后,TcpClient仍然连接.为什么

read返回0,如果对端通过close发送FIN。

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

:

如果接收Q不为空并且尝试发送close,则实体将发送RST。连接永远断开。

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