Windows 10でNetCoreを実行しています。私は2つのプログラムを持っています。次のようにNetCoreのC#TcpClient/TcpListenerの奇妙な動作を説明してください
実行順序は次のとおりです。
- 実行サーバ - クライアント
- 実行クライアントを処理するためのループがある - クライアントがそのジョブを行い、プロセスが二度目の
- 実行クライアントを終了します :
この配列は、以下のコードを使用してサーバからの次の出力を生成しますクライアントからの出力以下
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.
および3210:
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
つまり - クライアントを実行するための第2の試みは例外で終わります。それは奇妙な部分です。
問題を再現するための最小限のサンプルコードです。
Serverコード:
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が設定されている3行をすべて省略すると、違いはありません。私はfalseにNODELAYを設定している場合も違いはありません
new LingerState(true, 5)
にLingerStateを設定している場合も動作に違いはありません。言い換えれば、LingerStateとNoDelayの両方の値を設定しても、クラッシュには何の影響も与えないようです。クラッシュを防ぐ唯一の方法は、サーバー側のクライアントからの入力全体を読み取ることです。
これは奇妙なことです。誰かがそれを説明できるかどうかは不思議です。 NetCore 1.0.0およびWindows 10でのみテストされています。
申し訳ありませんが、「クラッシュを防止する唯一の方法は、サーバー側のクライアントからの入力全体を読み取ることです」という質問には既に書かれています。質問自体は、メッセージは読み取られません。 – Wapac