You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# NetworkStream.ReadAsync无法读取短于缓冲区长度的数据问题排查

问题修复方案:无法读取短于缓冲区长度的剩余数据

你的代码核心问题出在循环逻辑和流读取的处理上,具体问题点和修复方式如下:

问题根源

  1. 循环条件错误:当sizeReceived已经等于fileSize时,循环条件sizeReceived <= fileSize仍会让代码进入循环,调用ReadAsync等待更多数据,但此时文件已经接收完毕,没有数据会过来,导致程序停滞。
  2. 未处理流结束的情况: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 16:39:21