您的位置:首页 > 其它

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

2014-11-01 21:10 447 查看
最近项目需要实现一个通过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]");
}
结果问题虽然不出现了,但是原因没有找到,目前怀疑会不会与字符集有关。    

还请各位大虾帮忙看看有没有遇到过类似的问题,或者帮忙指出该问题的原因到底在哪?    
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  socket udp