Socket.BeginSend
非同期化がこれほど速く、予測できないのはなぜですか? 非同期であることはわかっていますが、すぐに完了することもできます。その場合IAsyncResult.CompletedSynchronously
は設定されています。CompletedSynchronously
8KB の送信バッファがいっぱいになるまでは true になると思います。以下のテスト ケース (簡潔にするために削除されたクリーンアップ コード) は、BeginSend
6 バイトのデータのみをバッファリングした後、(通常) 3 回目の反復で非同期になることを示しています。
TcpListener listener = new TcpListener(IPAddress.Any, 35001);
listener.Start();
Socket client = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp))
client.Connect(new IPEndPoint(IPAddress.Loopback, 35001));
Socket server = listener.AcceptSocket())
for (int i = 1; i <= 10; ++i)
{
bool sent = false;
IAsyncResult result = client.BeginSend(new byte[] { 1, 2, 3 }, 0, 3,
SocketFlags.None, r => sent = true, null);
Assert.IsTrue(result.CompletedSynchronously, // fails typ. on 3rd iteration
String.Format("Asynchronous on iteration {0}", i));
Assert.IsTrue(sent);
client.EndSend(result);
}
非同期になる正確な反復は、いくぶんランダムです。プロセスが開始されると、それは 3 です。その後、すべての新しいソケットに対して 1 になります。私は散発的に他の数字を見てきました。Socket.Send
(with Socket.Blocking = false
) は約 8KB で停止するため、8KB のソケット送信バッファがあることはわかっています。
メソッドSocket.SendAsync
は、常に非同期で完了することを除いて同様に動作します (つまり、直接バッファー書き込みを試みません)。Socket.SendAsync に関する私の関連する質問を参照してください。
BeginSend
パフォーマンス上の理由から、ほとんど同期する必要があります (非同期コールバックは遅くなります)。言うまでもなく、この予測不可能性は、低レベルの通信コードの単体テストとベンチマークを台無しにします。