TCP memcpy缓冲区使用C++返回垃圾数据

nut*_*les -1 c++ sockets

我正在做类似于Stack Overflow问题的事情处理来自recv()TCP的部分返回.

数据接收大于初始化的缓冲区(例如,1000字节).因此,使用更大尺寸的临时缓冲区(例如,10000字节).问题是收到的多个数据是垃圾.我已经将memcpy的偏移量检查到临时缓冲区,但我一直收到垃圾数据.

此示例显示了我的操作:

收到第一条消息:

memcpy(tmpBuff, dataRecv, 1000);
offSet = offSet + 1000;
Run Code Online (Sandbox Code Playgroud)

第二个消息:

memcpy(tmpBuffer + offSet, dataRecv, 1000);
Run Code Online (Sandbox Code Playgroud)

有什么我应该检查的吗?


我检查了发出的TCP十六进制.显然,发件人发送的邮件不完整.我的程序如何工作是当发件人发送邮件时,它将打包(邮件标题+实际邮件).消息头有一些元数据,其中一个是消息长度.

当接收方收到数据包时,它将使用消息头偏移量和消息头长度获取消息头.它将提取消息长度,检查当前数据包大小是否大于或等于消息长度,并将正确的消息大小返回给用户.如果数据包中剩余剩余数量的消息,它将把它存储到临时缓冲区并等待接收下一个数据包.当它收到下一个数据包时,它将检查消息头的消息长度并执行相同的操作.

如果发送方在数据包中打包三条消息,则每条消息都有自己的消息标题,指示消息长度.假设所有三条消息的长度均为300字节.还假设发送的第二条消息不完整,结果只有100字节.

当接收方收到数据包中的三条消息时,它将正确返回第一条消息.由于第二个消息不完整,我的程序将不知道,因此它将从第二个消息返回100个字节,从第三个消息返回200个字节,因为消息头指示总大小为300个字节.因此返回的第二条消息将有一些垃圾数据.

至于第三条消息,我的程序将尝试从消息头中获取消息长度.由于已返回前200个字节,因此消息头无效.因此,返回到我的程序的消息长度也将是垃圾.有没有办法检查完整的消息?

Kil*_*nDS 5

假设你期望在tcp连接上有7000个字节.在这种情况下,很可能您的消息将被拆分为tcp数据包,实际有效负载大小为1400字节(因此为5条消息).

在这种情况下,完全可能recv使用1000字节的目标缓冲区进行的连续调用将表现如下:

recv -> reads 1000 bytes (packet 1)
recv -> reads 400 bytes (packet 1)
recv -> reads 1000 bytes (packet 2)
recv -> reads 400 bytes (packet 2)
...
Run Code Online (Sandbox Code Playgroud)

现在,在这种情况下,当读取400字节数据包时,您仍然将完整的1000个字节复制到较大的缓冲区,实际上在它们之间粘贴了600字节的垃圾.实际上你应该只记忆收到的字节数,这是recv它自身的返回值.当然,您还应检查此值是0(套接字关闭)还是小于零(套接字错误).

  • +1.最常见的套接字编程错误是假设"recv"返回了你传入的字节数.IP碎片,TCP分段,tcp窗口大小和许多其他因素会影响返回的字节数.并且完全独立于与相应的发送调用()"发送"的字节数. (2认同)