一个关于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]");
    }

结果问题虽然不出现了,但是原因没有找到,目前怀疑会不会与字符集有关。

还请各位大虾帮忙看看有没有遇到过类似的问题,或者帮忙指出该问题的原因到底在哪?

时间: 2024-08-01 10:42:19

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

安卓使用Socket发送中文,C语言服务端接收乱码问题解决方案

今天用安卓通过Socket发送数据到电脑上使用C语言写的服务端,发送英文没有问题,可当把数据改变成中文时,服务端接收到的数据确是乱码. 突然想到,VS的预处理使用的是ANSI编码,而安卓网络数据都是UTF8格式的,这样直接使用printf打印出出来的当然是乱码,所以解决方法就是把UFT8格式的数据转换成ANSI! 避免大家遇到类似问题,少走弯路,我现在把自己找的转码函数贴出来! C语言文字编码转换函数: //UTF8转成Unicode wchar_t * UTF8ToUnicode( const

JAVA SOCKET网络编程,服务端接收多个客户端连接的实现

这是基于前面一篇文章的一个简单扩展,当然这不是最好的实现 服务端如果要想接收多个客户端连接,必须死循环去接收新的客户端的连接请求,一个完整的客户端服务端socket连接通过一个线程来维护 package com.tree.demo.socket; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.n

WebService或HTTP服务端接收请求转发消息到另一个服务端-实现思路

1.需求结构(WebService) A客户端<->B服务端<->C服务端 说明: a.在B服务端上面添加配置项(1.是否转发消息到C服务端:2.C服务端IP和端口): b.A客户端发消息到B服务端,B服务端收到消息判断是否需要转发,如果是需要转发就将消息转发给C服务端,然后消息再依次返回. 2.现在就是B服务端如何接受A客户端消息并直接转发给C服务端? 目前我找到就一下方案: a.apache camel:基于规则路由和中介引擎,貌似很强大时间紧,木有时间研究.... b.土办法

Linux c服务端接收图片c/c++语言module

---恢复内容开始--- 由于深度学习任务的需要,要在程序里面嵌入一个module. 这个module 的功能是接收来自ios客户端的图片.并且传送给深度学习分类器进行处理. 于是看了看各种各样的 module 实现方案. 1 先是用IO函数把图片以数组的方式存起来. 再和服务器建立连接,socket传这个数组. 然后服务器接收完数组以后就再运用IO函数 把数组以图片的方式存起来! 还有代码 bool ReadFileToBuffer( CString strFile,string& strBu

关于servlet服务端接收客户端发送的List&lt;?&gt;数据的问题

这些天由于任务需要,又研究了一下servlet,因为以前学习过客户端和服务器通过JSON串传输数据,知道可以在servlet中查询数据库,再将数据组装成JSON串发送给客户端,让客户端解析数据.但是这次由于涉及到客户端上传数据,经过servlet处理,然后存入数据库中.这样就不知道怎么处理了. 在实践过程发现,如果在客户端将数据组装成JSON串,在发送给servlet接收,用不了JSON的jar包(目测是需要导包的,因为servlet是在一个java工程中写的,JSON for java的包蛮难

解决.NET Web API生成的Help无Controller说明&amp;服务端接收不到请求

今天在用.NET Web API写一个接口的时候遇到一个问题.在Controller中新加了一个方法,客户端就不能请求接口了,当时建WEB API项目是用的VS默认设置,在服务端打断点一直没有进去,而APP端一直报服务端响应失败!奇怪的是连生成的Help API说明都没Controller说明. 这样也办法用WebAPITestClient测试,后来用想到了用HttpRequester插件请求一下接口果然出错了. <Error><Message>出现错误.</Message&

服务端接收不到ajax post请求的参数

问题描述 服务端使用request.getParameter()接收不到post请求的参数,导致业务逻辑抛出空指针异常. 解决途径 tomcat对post请求支持的字节数不受限制的配置发生变化.在tomcat容器在7.0.63版本之前,maxPostSize <= 0 都表示 tomcat对post请求支持的字节数不受限制,从7.0.63版本开始,仅是maxPostSize < 0 表示tomcat对post请求支持的字节数不受限制.将maxPostSize的值由0改为-1,问题得到解决.(m

Python Udp Socket

socket(套接字),传输层通信的端点,由IP和端口号组成(IP,Port),可以通过socket精确地找到服务器上的进程并与之通信 python2.6实现,基于AF_INET(网络套接字) 类型SOCKET_STREAM(TCP套接字),SOCKET_DGRAM(UDP套接字) UDP socket实现较TCP要简单,没有建立连接的过程,服务端无限循环接收数据,处理数据返回,客户端也无需建立通信连接, 直接发送数据接收数据即可 UDP socket通信逻辑 UDP服务端:创建socket>>

使用NewLife网络库构建可靠的自动售货机Socket服务端(一)

最近有个基于tcp socket 协议和设备交互需求,想到了新生命团队的各种组件,所以决定用NewLife网络库作为服务端来完成一系列的信息交互. 第一,首先说一下我们需要实现的功能需求吧 1,首先客户有一堆自动售货机的设备,设备连接socket服务端后 定时发送设备实时状态作为心跳信息,并且服务端需要下发信息予以确认. 2,需要知道设备的实时在线状态 3,设备需要实现微信,支付宝扫码支付需求,当客户买东西的时候选择扫码支付时,设备上报产品价格信息,支付方式,服务器下发微信或者支付宝的当面付二维