我都赞成多线程和异步任务,但放开控制不是我的一杯茶。
我正在做一个项目,其中一个进程通过 websockets 与多个目标进行通信,并且发送显然应该尽可能快,但必须相互同步。考虑将视频流同时传输到多个设备。因此,我不想在目标接收到第一帧之前继续发送下一帧。
使用.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 实现的理解全错了吗?是否不可能对数据发送的完整性进行回调/事件或类似的操作?我可以通过其他方式实现这一目标吗?同步执行这个真正的同步将是一个解决方案,但我似乎无法强制这样做。
啊!