UDP Socket 接收垃圾值

Posted

技术标签:

【中文标题】UDP Socket 接收垃圾值【英文标题】:UDP Socket receive Garbage Value 【发布时间】:2013-03-14 12:08:14 【问题描述】:

系统配置:Win XP (i7 2.1 Ghz) 外置 USB 网卡。 通讯:主从通讯。 约束 - 通信协议 UDP。

套接字配置: RecvFrom - 非阻塞。 使用 setsockopt 将套接字大小更改为 1*1024*1024。

我的设置包括一个通过 UDP 与主节点通信的节点,它在 UDP 帧的有效负载中发送分段数据。该分段数据由每个以太网帧 5 个帧组成。 从节点向主节点发送 1270 字节的分片数据。从站在 2 毫秒内发送 18 - 20 帧。

主设备会定期接收这些帧而不会丢弃它们。然而,来自 UDP 帧的有效负载数据随机包含 2 个正确片段,其余 3 个片段是垃圾值。我在 smae 片段中观察到了 wireshark 上的痕迹,可以观察到正确的数据,但是 recvfrom API 如何在这 3 个片段中收集垃圾数据。看起来实际信息是如何被这个垃圾值替换的。当我将数据包数量减少到每 2 毫秒 2 - 3 个时,这种行为就会下降。

从控制台跟踪:

_recvBuf[2]: 0x5b  _recvBuf[256: 0x5c  _recvBuf[510]: 0x5d  
_recvBuf[764: 0x5e  _recvBuf[1018: 0x5f

_recvBuf[2]: 0x60  _recvBuf[256: 0x61  _recvBuf[510]: 0x64  
_recvBuf[764: 0x0  _recvBuf[1018: 0x0

Expected and as in the Wireshark trace:
_recvBuf[510]: 0x64  --> should be _recvBuf[510]: 0x62
_recvBuf[764: 0x0  --> should be _recvBuf[510]: 0x63
_recvBuf[1018: 0x0  --> should be _recvBuf[510]: 0x64

并且垃圾值不规则地重复到 0xcd,用于随机数据包编号。

!!!数据包 200 - 错误 !!!数据包 20000 - 错误 !!!数据包 60000 - 错误 !!!数据包 2 - 错误

我无法理解为什么会这样。

代码:

receive()

rc = select(_sock_fd+1, &read_fd, &write_fd, &excep_fd, &to);

    if (rc == 0 )  
    acess = 1; 

    else if (rc == SOCKET_ERROR) 
    
        closesocket(_sock_fd);
        return -1;
     
    else 
    
        if (!FD_ISSET(_sock_fd, &read_fd)) 
        
            LogError("XCP: select() wrong socket descr");
            return -1;
        
        else
        

        rc = recvfrom(_sock_fd, (char *)_recvBuf, UDP_RECVBUFLEN, 0, (LPSOCKADDR)&_saddr, &cli_alen);

           printf("_recvBuf[3]: 0x%x  _recvBuf[2]: 0x%x  _recvBuf[256: 0x%x  _recvBuf[510]: 0x%x  _recvBuf[764: 0x%x  _recvBuf[1018: 0x%x\n",_recvBuf[3],_recvBuf[2],_recvBuf[256],_recvBuf[510],_recvBuf[764],_recvBuf[1018]);
            _recvBuf[*(&rc)]='\0';

            if(rc == SOCKET_ERROR) 
            
                closesocket(_sock_fd);
                return -1;
            


                    _recvBufLen = rc;

            if (_recvBufLen > 0) 
            
                int rc = 0;
                acess = 0;

                if (_rxNotification != NULL)
                    _rxNotification(_parent, _xhdl, _recvBuf, _recvBufLen);

                RxbufferLen=*(u16*)&_recvBufLen;

                /* Proto RX Queue Implementation Start */
                if(!(Fullqueue(Rxbufferqueue)))
                    Enqueue(Rxbufferqueue,_recvBuf);

                if(_recvBuf[4]==0xff)
                    acess = 1;
                else
                    acess = 0;

                return rc;
            
            else 
                return 0;
        
    

有关功能的其他信息:

void XcpTransportUdp::Enqueue (Queuetype &queue, unsigned char buf[MAX_BUFFER_SIZE_QUEUE],u16 _recvBufLen)  // Push Function for Queue

    Rxbufferqueue.BackPointer=(Rxbufferqueue.BackPointer+1)%MAX_BUFFER_IN_QUEUE;
    Rxbufferqueue.Recv_length[Rxbufferqueue.BackPointer]=_recvBufLen;
    memcpy(Rxbufferqueue.Buffer[Rxbufferqueue.BackPointer],buf,Rxbufferqueue.Recv_length[Rxbufferqueue.BackPointer]);

u16 XcpTransportUdp::Dequeue (Queuetype &queue, unsigned char Output_buffer[MAX_BUFFER_SIZE_QUEUE])  // Pop Function for Queue

    Rxbufferqueue.Frontpointer =(Rxbufferqueue.Frontpointer+1)%MAX_BUFFER_IN_QUEUE;
    BufLen=Rxbufferqueue.Recv_length[Rxbufferqueue.Frontpointer];
    memcpy(Output_buffer,Rxbufferqueue.Buffer[Rxbufferqueue.Frontpointer],Rxbufferqueue.Recv_length[Rxbufferqueue.Frontpointer]);
    return BufLen;

:::Edir1::: 我发现错误与内存初始化有关,而不是与套接字有关。 enqueue函数中的memcpy函数报长度为0cCD的错误。 有没有人知道这个问题的解决方案..?

【问题讨论】:

0xCD 通常表明您正在读取未初始化的内存。 您能否发布一段代码来说明您是如何从 UDP 套接字读取数据的? 我无法理解您想要什么。您希望我们指出您代码中的错误在哪里吗? 如您所见,printf 函数紧跟在 recvfrom 函数之后。例如,我得到大约 800 个以太网帧正确,然后 801 是错误的,然后下一个错误出现在 20000 帧。我无法理解,为什么套接字会收集垃圾。直到 800 帧它收集正确的值然后垃圾,然后直到 20000 正确的值,然后再次垃圾。更多的是这种行为是随机的。唯一的一致性是垃圾值。据我所知,代码没有任何问题 【参考方案1】:

我马上看到一件可疑的事情:

在使用返回码作为数组的索引之前,您应该检查返回码是否失败FIRST尤其是!我不认为设置_recvBuf[SOCKET_ERROR] = '\0'; 是安全的,但是,如果出现错误,这正是_recvBuf[*(&rc)] = '\0'; 行上会发生的事情。另外,当你可以只使用rc 时,*(&rc) 有什么意义?

另外,代码没有显示_recvBuf 的声明,所以我们必须假设它足够大,可以接收UDP_RECVBUFLEN 字符(我们在示例代码中没有看到其值的另一个符号。)真的需要在recv() 通话中将_recvBuf 转换为(char *) 吗?我问是因为您似乎将它视为其他地方的字符数组。我也不确定您是否在打印这些字节之前验证您是否阅读了您认为应该阅读的尽可能多的字节。

【讨论】:

我的Applogies,其实这个项目已经够大了。尽管如此,_recvbuf 被声明为 unsigned char _recvBuf 和 _sendBuf = (u8 *)calloc(1,XCP_MAX_UDP_PACKET_SIZE);初始化 XCP_MAX_UDP_PACKET_SIZE = 0x100000 (1048576) _recvBuf[*(&rc)] = '\0';是废话请忽略。我不认为将 recbuf 转换为 char 会收集垃圾,因为在整个流程中我没有转换为任何其他类型。如果我错了,请纠正我。

以上是关于UDP Socket 接收垃圾值的主要内容,如果未能解决你的问题,请参考以下文章

终端通过GPRS发送UDP数据到固定IP:端口号,socket recvfrom接收不到数据,但却有返回值,如何解决

c#,socket无法接收分片的UDP数据包

UDP 协议 C# UdpClient乱序接收数据包丢失的问题 Socket ReceiveBufferSize

UDP接收端和发送端_Socket编程

C# UDP Socket:获取接收者地址

在UDP Socket java android上发送和接收数据