1

Socket.BeginSend非同期化がこれほど速く、予測できないのはなぜですか? 非同期であることはわかっていますが、すぐに完了することもできます。その場合IAsyncResult.CompletedSynchronouslyは設定されています。CompletedSynchronously8KB の送信バッファがいっぱいになるまでは true になると思います。以下のテスト ケース (簡潔にするために削除されたクリーンアップ コード) は、BeginSend6 バイトのデータのみをバッファリングした後、(通常) 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パフォーマンス上の理由から、ほとんど同期する必要があります (非同期コールバックは遅くなります)。言うまでもなく、この予測不可能性は、低レベルの通信コードの単体テストとベンチマークを台無しにします。

4

0 に答える 0