现在的位置: 首页 > 综合 > 正文

java 和 C 在网络编程中的问题

2019年04月21日 ⁄ 综合 ⁄ 共 1387字 ⁄ 字号 评论关闭

这周公司分配任务让写一个UDP服务器端用于单向接收数据包;本来程序不是很复杂,但还是由于字节序的问题在调试的过程中浪费了大量的时间

主要原因是客户端是采用java代码编写的,而我一直对java又不是很熟悉,现在做个总结

1.java 与 C 的数据类型

     java 与 c  的数据类型基本上是能一一对上的,主要区别是java 的long 型是8字节,而C 语言在32位机上long型为4字节,在64位机上是8字节

     为了安全起见,在数据接收的时候最好用long long型,这样就能保证代码能跑在不同平台上

2.字节序问题

     做过网络编程的都知道字节序的问题,主要是由于CPU平台的不同造成的,我觉得因该是个历史遗留问题吧。

     在写这个程序的时候,对端和我都是在x86 pc上跑的,而且在封装udp包的时候是拆分成字节的形式发送的,到了对端重新组装,所以我觉得不用多考虑字节序的问题

     但是问题就出在这了,对端发送的数据包里long型的数据到我这边之后值不是我应该得到的值,我第一个反应是字节序的问题,然后使用htonl简单尝试之后发现不对就去尝试别的方法了,最后通过抓包发现传过来的数据就是字节序到装了,这是什么原因呢,我已经尝试过字节序转换为什么不行呢,通过反复查阅资料,终于找出了原因

         最主要的原因:jave 只有大端存储

         由于对字节序和 java 语言不是很熟悉,我一直以为字节序是CPU平台不同造成的,其实不同语言之间也存在字节序的问题,与C 语言不同,java 语言在任何平台下都是大端存储的,所以在这样跨语言交叉通讯的时候要格外小心。

    

          第二个原因:

        数据结果不对,我第一时间就想到了可能是字节序的问题,可是还是在使用htol之后结果还是不对的,这是为什么,我们看一下网络字节序转换的几个函数:

       uint32_t htonl(uint32_t hostlong);

       uint16_t htons(uint16_t hostshort);

       uint32_t ntohl(uint32_t netlong);

       uint16_t ntohs(uint16_t netshort);

      仔细看这几个函数并不支持 8 字节数据的字节序转换,如果用htonl 转换 8位的long型的话,高位就会丢失,变成全零,最后我解决这个问题的办法是自己写了一个函数去手动转换

    好了,明白了这两点,在编写这类程序的时候就没多大问题了。

    最后一点有趣的是,我发现虽然这组函数分了 htonl 和 ntohl,但对一个待转换的数而言,这两个函数随便哪一个都是转换了字节序

   即: 使用两次同一个函数和分别使用一次两个函数,结果都是一样的:

      int a = 48;           / /a-->    0x30 0x00 0x00 0x00

     int b = htonl(a)    // b-->    0x00 0x00 0x00 0x30

     int c = ntohl(a)       // c-->  0x00 0x00 0x00 0x30

     int d = ntohl(c)      // d-->  0x30 0x00 0x00 0x00

   为什么要将同样功能的函数分为两个实现,哪位大神来告诉我下

   e-mail : mhpmii@126.com

        

抱歉!评论已关闭.