我正在做类似于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个字节,因此消息头无效.因此,返回到我的程序的消息长度也将是垃圾.有没有办法检查完整的消息?
假设你期望在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(套接字关闭)还是小于零(套接字错误).