我在Windows 10上运行NetCore,我有两个程序-服务器和客户端都在本地运行。

执行顺序如下:


运行服务器-有一个处理客户端的循环
运行客户端-客户端执行其工作,过程终止
第二次运行客户端


此序列使用以下代码从服务器生成以下输出:

Waiting for client.
Reading message.
Incoming message: This message is longer than what
Sending message.
Closing connection.
Waiting for client.
Reading message.
Incoming message: This message is longer than what
Sending message.
Closing connection.
Waiting for client.


以及客户端的以下输出:

Connecting to server.
Sending message.
Reading message.
Incoming message: Thank you!


Connecting to server.
Sending message.
Reading message.

Unhandled Exception: System.AggregateException: One or more errors occurred. (Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.) ---> System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host


换句话说,第二次运行客户端的尝试以异常结束。那是奇怪的部分。

这是我用于重现此问题的最小代码示例。

服务器代码:

public static async Task StartServerAsync()
{
  TcpListener listener = new TcpListener(IPAddress.Any, 1234);
  listener.Server.NoDelay = true;
  listener.Server.LingerState = new LingerOption(true, 0);
  listener.Start();

  while (true)
  {
    Console.WriteLine("Waiting for client.");
    using (TcpClient client = await listener.AcceptTcpClientAsync())
    {
      client.NoDelay = true;
      client.LingerState = new LingerOption(true, 0);

      Console.WriteLine("Reading message.");
      using (NetworkStream stream = client.GetStream())
      {
        byte[] buffer = new byte[32];
        int len = await stream.ReadAsync(buffer, 0, buffer.Length);
        string incomingMessage = Encoding.UTF8.GetString(buffer, 0, len);
        Console.WriteLine("Incoming message: {0}", incomingMessage);


        Console.WriteLine("Sending message.");
        byte[] message = Encoding.UTF8.GetBytes("Thank you!");
        await stream.WriteAsync(message, 0, message.Length);
        Console.WriteLine("Closing connection.");
      }
    }
  }
}


客户代码:

public static async Task StartClientAsync()
{
  using (TcpClient client = new TcpClient())
  {
    client.NoDelay = true;
    client.LingerState = new LingerOption(true, 0);

    Console.WriteLine("Connecting to server.");
    await client.ConnectAsync("127.0.0.1", 1234);

    Console.WriteLine("Sending message.");
    using (NetworkStream stream = client.GetStream())
    {
      byte[] buffer = Encoding.UTF8.GetBytes("This message is longer than what the server is willing to read.");
      await stream.WriteAsync(buffer, 0, buffer.Length);

      Console.WriteLine("Reading message.");
      int len = await stream.ReadAsync(buffer, 0, buffer.Length);
      string message = Encoding.UTF8.GetString(buffer, 0, len);

      Console.WriteLine("Incoming message: {0}", message);
    }
  }
}


奇怪的是,如果我们将客户的信息从

"This message is longer than what the server is willing to read."




"This message is short."


客户端的两个实例均完好无损,并产生相同的输出。

请注意,如果我省略了设置LingerState的所有三行,则没有区别。另外,如果我将LingerState设置为

new LingerState(true, 5)

如果将NoDelay设置为false,也没有区别。换句话说,在任一侧将任何值设置为LingerState和NoDelay似乎都对崩溃没有任何影响。防止崩溃的唯一方法是从服务器端的客户端读取整个输入。

这很奇怪,我想知道是否有人可以解释这一点。我不确定它是否也适用于.NET Framework,仅在NetCore 1.0.0和Windows 10上进行了测试。

最佳答案

最终由.NET Core团队在GitHub上回答。

长答案-查看https://github.com/dotnet/corefx/issues/13114的最新评论

简短答案-


  该行为是预期的,并且是设计使然。

10-08 02:16