.NET 8中MS Quic客户端接收数据偶尔损坏的问题与解决
.NET 8 MS Quic流传输数据损坏问题的解决方案
问题场景
在本地WiFi网络中使用.NET 8的MS Quic实现服务器到客户端的数据流传输时,客户端接收的部分流数据损坏,仅约60%的流能完整正确接收。传输的流为约15KB的byte[],结构如下:
- 前50字节:写入时间戳
- 中间50字节:包计数器ID
- 剩余约15KB:PNG文件字节数据
测试中调整了不同传输频率(如每2秒传输一次),排除了带宽和硬件故障的可能性,损坏流仅约5%的字节出现错误。
根因分析
问题核心是客户端读取流时未校验读取数据的长度:单次调用ReadAsync无法保证一次性返回全部预期数据,原代码直接使用单次读取的结果进行业务处理,导致不完整的字节数组被解析,最终引发数据损坏。
修复后的关键读取代码
通过循环调用ReadAsync,直到读取到预期的完整数据长度,解决了数据不完整的问题:
public async Task ReceiveStreamAndSendFeedback() { int msgCounter = 0; int receiveArrayLength = 50 + 50 + 15284; try { if (null == _incomingStream) { _incomingStream = await _connection.AcceptInboundStreamAsync(); } if (null == _outgoingStream) { _outgoingStream = await _connection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional); } bool isRunning = true; bool isStreamStartAnnounced = false; while (isRunning) { byte[] buffer = new byte[receiveArrayLength]; int streamLength = 0; // 循环读取直到获取完整的预期数据长度 while (streamLength < receiveArrayLength) { streamLength += await _incomingStream.ReadAsync(buffer, streamLength, receiveArrayLength - streamLength); } // 原错误实现:仅单次读取,未校验长度 // streamLength = await _incomingStream.ReadAsync(buffer, 0, receiveArrayLength); // 后续业务逻辑处理 } } // 异常处理代码 }
完整代码示例
服务器入口代码
QuicServerPrototype quicServerPrototype = new QuicServerPrototype(); await quicServerPrototype.Initi(); List<Task> tasks = new List<Task>(); tasks.Add(quicServerPrototype.SendStream()); tasks.Add(quicServerPrototype.ReceiveFeedback()); // 并行启动所有任务 await Task.WhenAll(tasks);
QuicServerPrototype.cs包含初始化、流发送、反馈接收的完整逻辑
客户端入口代码
QuicClientPrototype quickClientPrototype = new QuicClientPrototype(); try { await Task.Delay(4000); await quickClientPrototype.Initi(); await quickClientPrototype.ReceiveStreamAndSendFeedback(); } catch (Exception e) { throw new Exception(e.Message,e); }
QuicClientPrototype.cs包含初始化、流接收及反馈发送的完整逻辑
内容的提问来源于stack exchange,提问作者MaciejW
相关产品推荐
相关产品推荐

