服务器关闭连接后,TcpClient仍然连接。为什么呢?

时间:2015-05-22 09:58:00

标签: c# tcp connection tcpclient

我有一台运行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()来关闭连接,以下调用{ {1}}失败并出现异常。到现在为止还挺好。这就是我的期望。

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

有人可以解释为什么第二种情况会像这样发生吗?或者如何管理它,在这种情况下获得例外?

1 个答案:

答案 0 :(得分:1)

如果对等方通过在其末尾执行read发送了FIN,则

close返回零。

read从对等方为RST引发异常(ECONNRESET)。

现在:

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

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