一个关于UDP socket服务端接收长度不正确的问题

最近项目需要实现一个通过UDP协议和远端服务平台通讯的需求,简要描述如下:
本端为嵌入式linux路由器(udp客户端,linux C编码),远端为租用的阿里云服务器(udp服务端,java编码),
通信协议为UDP,本端会定时向远端服务器发送消息。

在实现和调试过程中发现一个问题:
1)将远端服务程序放在实验室pc机上调试没有问题,即“路由器-PC”交互正常。
2)将远端服务程序放至阿里云服务器上运行,结果服务端收到的udp消息会多出4个字节,偶尔还会多出6个,多出的字节是 EF BF 之类的。
3)在远端服务器通过tcpdump抓包发现,tcpdump抓到的udp报文长度是正确的,并没有多出4个字节。
4)在检查并尝试字节序、字节对齐等问题后,仍然没有找到问题的原因。
5)最后,想到把消息中传输数值的地方,全部转换为字符串方式传输,结果问题没了,但是原因还无法确定。
6)在网上搜到一篇类似问题的帖子,但是,没有给出最终解决方案,链接如下:
       http://bbs.csdn.net/topics/370180910
   
1. 发现问题的代码实现,即消息传输中有数值
    unsigned char tmpBuf[DIAG_NOTIFY_LEN] = {0};
    unsigned short usCrc = 0, uslen = 0;
    
    memset(tmpBuf, 0, DIAG_NOTIFY_LEN);
    ((NotifyHeader *)(tmpBuf))->HeaderFlag = htons(DIAG_MSG_HEADER);
    ((NotifyHeader *)(tmpBuf))->MsgType = htons(DIAG_NOTIFY_MSG);
    ((NotifyHeader *)(tmpBuf))->SeqNum = htons(g_usLastSeq);
    ((NotifyHeader *)(tmpBuf))->DataLen = htons(strlen(macBuf));
    sprintf(tmpBuf+sizeof(NotifyHeader), "%s", macBuf);

    uslen = sizeof(NotifyHeader) + strlen(macBuf);
    usCrc = CRC16(tmpBuf, uslen);
    *(tmpBuf+uslen) = (usCrc & 0xff00) >> 8;
    *(tmpBuf+uslen+1) = usCrc & 0x00ff;

    if(0 > sendto(g_diagSockFd, tmpBuf, uslen+DIAG_CRC_LEN, 0, g_pstAddrInfo->ai_addr, g_pstAddrInfo->ai_addrlen))
    {
        perror("diag_notify [sendto]");
    }
   
    关键数据结构定义为:
    typedef struct tagNotifyHeader
    {
        unsigned short HeaderFlag;
        unsigned short MsgType;
        unsigned short SeqNum;
        unsigned short DataLen;
    }NotifyHeader;
    考虑到字节对齐问题,定义时特意注意了一下保证数据结构的字节对齐。
    另外,为了彻底排除字节对齐的影响,还尝试了单个字节逐一赋值的方式,即
    *tmpBuf = (DIAG_MSG_HEADER & 0xFF00) >> 8;
    *(tmpBuf+1) = DIAG_MSG_HEADER & 0x00FF;
    ......
    结果问题依旧存在,后来想到全部转换为字符串的方式传输(如下),结果服务器端接收ok。

2. 将消息中的数值全部转换为字符串方式传输,服务器端接收正常
    unsigned char tmpBuf[DIAG_NOTIFY_LEN] = {0};
    unsigned short usCrc = 0, uslen = 0;    
    
    memset(tmpBuf, 0, DIAG_NOTIFY_LEN);
    uslen = sprintf(tmpBuf, "%x", DIAG_MSG_HEADER);
    uslen += sprintf(tmpBuf+uslen, "%x", DIAG_NOTIFY_MSG);
    uslen += sprintf(tmpBuf+uslen, "%4x", g_usLastSeq);
    uslen += sprintf(tmpBuf+uslen, "%4x", strlen(macBuf));
    uslen += sprintf(tmpBuf+uslen, "%s", macBuf);
    usCrc = CRC16(tmpBuf, uslen);
    uslen += sprintf(tmpBuf+uslen, "%4x", usCrc);
    
    if(0 > sendto(g_diagSockFd, tmpBuf, uslen, 0, g_pstAddrInfo->ai_addr, g_pstAddrInfo->ai_addrlen))
    {
        perror("diag_notify [sendto]");
    }
结果问题虽然不出现了,但是原因没有找到,目前怀疑会不会与字符集有关。    
还请各位大虾帮忙看看有没有遇到过类似的问题,或者帮忙指出该问题的原因到底在哪?    

你可能感兴趣的:(网络编程)