0

私は皆、マルチスレッド化と非同期タスクに賛成ですが、制御を手放すことは私の好みではありません。

私は、1 つのプロセスが websocket を介して複数のターゲットと通信しているプロジェクトに取り組んでおり、送信は明らかに可能な限り高速である必要がありますが、互いに同期する必要があります。ビデオストリームを複数のデバイスに同時にストリーミングすることを考えてみてください。したがって、最初のフレームがターゲットによって受信される前に、次のフレームを送信し続けたくありません。

.net WebSockets を使用する場合、HttpListner と Kestrel 実装の両方でこれを試しました (多かれ少なかれ同じだと思います)。socket.SendAsync はデータを受信し、送信する前にローカルでバッファリングしているようです。実際に送信される前に TaskCompleted 。これは、送信タスクが基本的に即座に完了することを意味します。

もちろん、パケット全体が受信されたときに受信者が ACK を送信する ACK スキーマを実装することもできますが、それ自体がプロセスを遅くすることになります。キューに入れられたパッケージを継続的に送信しようとするためです。

これは基本的に、2048b のチャンクでデータを送信するコードです。

Log.Info($"Send {sendBytes.Length}b");
if (socket!.State == WebSocketState.Open)
{
    await socket.SendAsync(
        sendBuffer,
        WebSocketMessageType.Binary,
        endOfMessage: true,
        cancellationToken: cts
        );
}
Log.Info($"Done "); 

ここでの await は実際には送信が完了するのを待つと思いますが、そうではありませんが、タスクの完了を待っているようです。

受信者側では、前後にデバッグ応答を使用してデータを処理しています。

wsClientSession.send("REC " + (String)payloadLength + "b");
ProcessFrame(payload, payloadLength);
wsClientSession.send("ACK " + (String)payloadLength + "b");

送信者側のログには次のように表示されます。

  • スレッド 28 は送信スレッドであり、信じられないほど高速に完了します。6198 バイトを送信する必要があり、これを 4 回の送信でチャンクします。最初のパケットがサーバーを離れる前に、すべてが完了していることは明らかです。
  • 残りのスレッドは、デバッグ応答の非同期受信者です。
  • (サイズの違いはデータの暗号化によるものです)
2022-02-07 16:03:34.8887 threadid:28 # Info # Send 6198b to 5d8263c6-909c-47a1-b4d0-57d74d6a4665
2022-02-07 16:03:34.8887 threadid:28 # Info # Send 2048b
2022-02-07 16:03:34.8887 threadid:28 # Info # Done
2022-02-07 16:03:34.8887 threadid:28 # Info # Send 2048b
2022-02-07 16:03:34.8887 threadid:28 # Info # Done
2022-02-07 16:03:34.8887 threadid:28 # Info # Send 2048b
2022-02-07 16:03:34.8887 threadid:28 # Info # Done
2022-02-07 16:03:34.8887 threadid:28 # Info # Send 128b
2022-02-07 16:03:34.8887 threadid:28 # Info # Done
2022-02-07 16:03:34.8887 threadid:28 # Info # Send done to 5d8263c6-909c-47a1-b4d0-57d74d6a4665
2022-02-07 16:03:35.0024 threadid:7 # Info # 5d8263c6-909c-47a1-b4d0-57d74d6a4665 - REC 2030b
2022-02-07 16:03:35.0090 threadid:7 # Info # 5d8263c6-909c-47a1-b4d0-57d74d6a4665 - ACK 2030b
2022-02-07 16:03:35.0090 threadid:17 # Info # 5d8263c6-909c-47a1-b4d0-57d74d6a4665 - REC 2030b
2022-02-07 16:03:35.0260 threadid:33 # Info # 5d8263c6-909c-47a1-b4d0-57d74d6a4665 - ACK 2030b
2022-02-07 16:03:35.0260 threadid:33 # Info # 5d8263c6-909c-47a1-b4d0-57d74d6a4665 - REC 2030b
2022-02-07 16:03:35.0260 threadid:30 # Info # 5d8263c6-909c-47a1-b4d0-57d74d6a4665 - ACK 2030b
2022-02-07 16:03:35.0373 threadid:17 # Info # 5d8263c6-909c-47a1-b4d0-57d74d6a4665 - REC 108b
2022-02-07 16:03:35.0373 threadid:4 # Info # 5d8263c6-909c-47a1-b4d0-57d74d6a4665 - ACK 108b

さて、この WebSocket 実装に関する私の理解はすべて間違っていますか? データ送信完了時にコールバック/イベントなどを行うことはできませんか? これを別の方法で達成できますか?これを真に同期的に実行することは解決策ですが、それを強制することはできないようです。

ガーッ!!

4

1 に答える 1