C# NetworkStream.ReadAsync无法读取短于缓冲区长度的数据问题排查
问题修复方案:无法读取短于缓冲区长度的剩余数据
你的代码核心问题出在循环逻辑和流读取的处理上,具体问题点和修复方式如下:
问题根源
- 循环条件错误:当
sizeReceived已经等于fileSize时,循环条件sizeReceived <= fileSize仍会让代码进入循环,调用ReadAsync等待更多数据,但此时文件已经接收完毕,没有数据会过来,导致程序停滞。 - 未处理流结束的情况:
ReadAsync在流没有更多数据时会返回0,你的代码没有处理这种情况,会导致循环一直阻塞在ReadAsync调用上。
修复后的代码
// 循环读取直到接收完所有数据,或者流结束 while (sizeReceived < fileSize) { bytesRead = await streamNET.ReadAsync(bufferArray, 0, bufferArray.Length); // 流已结束,没有更多数据,直接退出循环(可添加文件不完整的错误处理) if (bytesRead == 0) { // 可选:记录日志、向服务器发送接收失败通知等 break; } output.Write(bufferArray, 0, bytesRead); // 写入接收的字节 packetNumber++; sizeReceived += bytesRead; if (sizeReceived > (0.9 * fileSize)) OutputText3.text = $" T3 : Received: {fileName}, packets = {packetNumber}, sizeReceived = {sizeReceived} bytes."; // 检查是否已经接收完所有数据 if (sizeReceived == fileSize) { // 从请求列表中移除文件名 ObjectListNet.RemoveAll(x => x == fileName); // 向服务器发送ACK data = Encoding.UTF8.GetBytes("Success"); await streamNET.WriteAsync(data, 0, data.Length); // 用异步Write保持逻辑一致性 break; } }
关键修改说明
- 调整循环条件:把
sizeReceived <= fileSize改为sizeReceived < fileSize,确保已经接收完所有数据时不会再进入读取循环。 - 处理ReadAsync返回0的情况:当返回0时,说明流已经关闭或者没有更多数据,直接退出循环,避免无限等待。
- 异步写入ACK:把同步的
Write改为await WriteAsync,保持异步逻辑一致性,避免阻塞调用线程。
另外,建议接收文件前确认fileSize的准确性,避免因文件大小信息错误导致的接收异常。
内容的提问来源于stack exchange,提问作者Asterios Papaioan
相关产品推荐
相关产品推荐

