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

使用Socket.ReceiveAsync(Memory<byte>)接收时内存无内容的问题排查

TCP ReceiveAsync(Memory)返回有效长度但缓冲区无数据的问题排查与解决

问题描述

在TCP接收编程中,使用ReceiveAsync(Memory<byte>, SocketFlags, CancellationToken)重载方法时,返回的reclen大于0,但目标缓冲区tcpRecReserve中未发现接收的数据;切换到ReceiveAsync(ArraySegment<byte>, SocketFlags)重载后,数据能正常写入tcpRecReserve。

相关代码:

public async Task BeginTcpRecieve()
{
    try
    {   
        //ArraySegment<byte> bytes = new ArraySegment<byte>(tcpRecReserve,catchNum, tcpRecReserve.Length - catchNum);
        Memory<byte> memory = new Memory<byte>(tcpRecReserve, catchNum, tcpRecReserve.Length - catchNum);
        int reclen = await tcpSocket.ReceiveAsync(memory, SocketFlags.None);
        HandleReceive(reclen);
        await BeginTcpRecieve();
    }
    catch (SocketException e)
    {
        print(e.ErrorCode + "/" + e.Message); 
        isConnected= false;
    }
}

问题原因

  1. Memory的偏移特性:你创建的Memory<byte>是基于tcpRecReserve数组从catchNum索引位置开始的子段,接收的数据会写入这个子段的起始位置(即tcpRecReserve[catchNum]及之后的区域),而非数组的开头。如果调试时只查看tcpRecReserve数组的起始部分,会误以为没有数据。
  2. 调试工具的显示差异:部分调试工具对Memory<byte>的可视化不如ArraySegment<byte>直观,容易忽略其偏移属性,导致误判数据未写入。
  3. 数据处理逻辑遗漏偏移:HandleReceive方法如果直接处理整个tcpRecReserve数组,而非catchNum偏移后的区域,会导致无法读取到实际接收的数据。

解决方法

  • 调整调试查看位置:调试时重点查看tcpRecReserve数组中从catchNum索引开始的连续reclen个字节,确认数据是否写入。
  • 修正数据处理逻辑:在调用HandleReceive时传入偏移量和实际接收长度,确保处理的是正确的缓冲区区域,示例修改如下:
// 修改BeginTcpRecieve中的调用逻辑
HandleReceive(catchNum, reclen);

// 对应调整HandleReceive方法
private void HandleReceive(int offset, int length)
{
    // 提取实际接收的数据段
    Span<byte> receivedSpan = tcpRecReserve.AsSpan(offset, length);
    // 后续数据处理逻辑...
}
  • 统一缓冲区构造参数:确保Memory<byte>的构造参数(偏移量、长度)和之前ArraySegment<byte>完全一致,维持相同的缓冲区操作逻辑。

内容的提问来源于stack exchange,提问作者Nocpe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 03:17:18