【发布时间】:2017-03-08 13:56:21
【问题描述】:
我在 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 上进行了测试。
【问题讨论】:
标签: c# .net tcpclient .net-core tcplistener