java与 C++ 之间进行 SOCKET 通讯要点简要解析

作者:看引擎 出处:博客 2013-07-11 06:57

  Endian定义: 在计算机系统体系结构中用来描述在多字节数中各个字节的存储顺序。

  big-endian也称高位在前、大端在前。是 计算机体系结构中一种描述多字节存储顺序的术语,在这种机制中最重要字节(MSB )存放在最低端的地址 上。采用这种机制的处理器有Mortolora PowerPC 微处理器系列和绝大多数的 RISC 处理器。

  big-endian 最直观的字节序:

  内存地址从左到右与值由低到高的顺序相对应。

  little-endian也称低位在前、小端在前。 计算机体系结构中一种描述多字节存储顺序的术语,在这种机 制中最不重要字节(LSB )存放在最低端的地 址上。采用这种机制的处理器有 Intel x86 系列微处理器和一些网络通信设备。该术语除了描述多字节存储顺序外还常常用来描述一个字节中各个比特的排放次序 ,这里仅讨论多字节存储循序 。

  little-endian是最符合人的思维的字节序,低与低,高与高一一对应:

  地址低位存储值的低位

  地址高位存储值的高位

  下面举一个例子具体说明 big-endian 与 little-endian:

  int nValue = 0×01020304;

  上面的整型nValue 有 4 个字节,其中 01 为最高位的字节, 04 为最低位的字节。那么在内存(或文件)中,该值的存储循序为:

  内存(或文件)地址:0×12000001 0×12000002 0×12000003 0×12000004

  Big-endian : 01 02 03 04

  Little-endian : 04 03 02 01

  如果用一个byte 数组来保存的话,也就是如下:

  Big-endian模式下: byte byValue[] = {0×01, 0×02, 0×03, 0×04};

  Little-endian模式下: byte byValue[] = {0×04, 0×03, 0×02, 0×01};

  Big-endian 或是 little-endian的判断:

  bool IsLittleEndian ()

  {

  int i = 1;

  char * p = ( char *)& i ;

  i f ( * p = 1 )

  return true ; // 小端

  else

  return false ; // 大端

  }

  在各种计算机体系结构中,对于字节、字等的存储机制有所不同,因而引发了计算机通信领域中一个很重要的问题,即通信双方交流的信息单元(比特、字节、字、双字等等)应该以什么样的顺序进行传送。如果不达成一致的规则, 通信双方 将无法进行正确的编/ 译码从而导致通信失败。

  通常所说的网络字节序(Network Byte Order )就是遵循 big-endian 规则。实际通信过程中,通信双方需要把数据按照 big-endian 编码再通过网络传输。

  通常所说的主机字节序(Host Byte Order ),与 CPU 的字节序一致。 x86 系列主机的字节序都是 little-endian 桂册。所有 little-endian 规则主机直接通过网络通讯的时候,需要进行字节序转化。

  为了进行转换 bsd socket 提供了转换的函数 有下面四个

  htons 把 unsigned short 类型从主机 字节 序转换到 网络字节序

  htonl 把 unsigned long 类型从主机 字节 序转换到 网络字节序

  ntohs 把 unsigned short 类型从 网络字节序 转换到主机 字节 序

  ntohl 把 unsigned long 类型从网络 字节 序转换到主机 字节 序

  在使用little endian 的系统中这些函数会把字节序进行转换

  在使用big endian 类型的系统中这些函数会定义成空宏

  由于Java 运行需要自己的虚拟机来支持,所以 Java 程序所支持的字节序与 Java 虚拟机一致。Java 虚拟机遵循的是 big-endian 规则。所以可以把 Java 字节序看作是遵循 big-endian 规则的主机字节序。

  4.1 字节序问题

  一直以来都在进行着C++ 上面的网络开发,发现在 C++ 上面进行通讯的时候,基本上都没有考虑到网络字节序的问题,特别是网络应用中的用户数据。大家都知道网络通讯传输的都是字节流的数据,于是都是定义一个 char 类型的缓冲区,然后不管 int , WORD, DWORD 还是其他自定义类型的结构对象也好,都直接 memcpy() 拷贝到缓冲区,直接发送出去了,根本都没有考虑所传输数据的网络字节序问题。如果非要说一点关注了网络字节序问题的话,那就是有一个地方,大家都回去用到的,也就是网络通讯端口,把端口号赋值给 sockaddr_in .sin_port之时大家都会使用了htons() ,也就是把端口号从主机字节序转化为网络字节序。

  因为这些程序的服务器端也好,客户端也好,都是在x86 系列系统下运行,并且都是 C++ 编译出来的,所以不会因为字节序而出现问题。

  现在所做项目,涉及到Java 与 C++ 之间的 SOCKET 通讯,这样的情况下,就需要大家都按规则来办事了, C++ 方面传输的多字节类型数据还请从主机字节序转化成网络字节序再进行传输。

  当然,数据是由程序员来组合的,也是由程序员来解析的,所以如果不按标准行事也是可以的。但是就需要在解析数据的时候注意好了。

  建议还是按标准行事,把数据转化成网络字节序。

  PS:

  Java与 Windows 平台下其他开发语言之间进行数据交与,也需要遵循该原则;

  Java下读写 Windows 平台下其他开发语言保存的数据,或是 Windows 平台下其他语言读写Java 保存的数据,也需要注意字节序问题。

  4.2 字节对齐问题

  #include

  using namespace std ;

  typedef struct tag_S1

  {

  char s_szValue [8];

  char s_cValue ;

  } S1 ;

  typedef struct tag_S2

  {

  int s_nValue1 ;

  char s_szValue [8];

  char s_cValue ;

  int s_nValue2 ;

  } S2 ;

  typedef struct tag_S3

  {

  int s_nValue ;

  char s_cValue ;

  } S3 ;

  #pragma pack ( push , 1)

  typedef struct tag_S4

  {

  int s_nValue ;

  char s_cValue ;

  } S4 ;

  #pragma pack ( pop )

  int main ( int argc , char * argv [])

  {

  cout << “sizeof(S1):” << sizeof ( S1 ) << endl ;

  cout << “sizeof(S2):” << sizeof ( S2 ) << endl ;

  cout << “sizeof(S3):” << sizeof ( S3 ) << endl ;

  cout << “sizeof(S4):” << sizeof ( S4 ) << endl ;

  system ( “pause” );

  return 0;

  }

  上面的程序在 WinXP sp3 + VS2008Sp1下运行结果如下:

  sizeof(S1):9

  sizeof(S2):20

  sizeof(S3):8

  sizeof(S4):5

  请按任意键继续. . .

  Win32位平台下的微软 C 编译器 (cl.exe for 80×86) 的对齐策略:

  1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;

  备注:编译器在给结构体开辟空间时,首先找到结构体中最宽的基本数据类型,然后寻找内存地址能被该基本数据类型所整除的位置,作为结构体的首地址。将这个最宽的基本数据类型的大小作为上面介绍的对齐模数。

  2) 结构体每个成员相对于结构体首地址的偏移量( offset )都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节( internal adding );

  备注: 为结构体的一个成员开辟空间之前,编译器首先检查预开辟空间的首地址相对于结构体首地址的偏移是否是本成员的整数倍,若是,则存放本成员,反之,则在本成员和上一个成员之间填充一定的字节,以达到整数倍的要求,也就是将预开辟空间的首地址后移几个字节。

  3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要,编译器会在最末一个成员之后加上填充字节( trailing padding )。

  备注:结构体总大小是包括填充字节,最后一个成员满足上面两条以外,还必须满足第三条,否则就必须在最后填充几个字节以达到本条要求。

  Windows 32位系统下, VC 中,默认的字节对齐方式是 4 字节对齐。

  sizeof(S1) :因为结构中数据类型都是 char ,最宽基本类型大小是 1 ,所以结构大小为 9, S1 没有进行填充;

  sizeof(S2)、 sizeof(S3) : S2 , S3 就被填充了一定的字节;

  sizeof(S4):因为设置了对齐方式为 1 字节对齐,所以不会被填充。

  在Java 与 C++ 进行 SOCKET 通讯的 C++ 端程序,建议涉及网络通讯的结构使用 1 字节对齐方式,不然 Java 端会增加数据处理的复杂度。

  4.3 Java与 C++ 之间基本数据类型的差别

  需要注意以下几个数据类型的区别(32 位系统下 ) :

  C++ Java

  char———1byte Byte———-1byte

  Char———-2byte2

  long———4bytes long———-8bytes

  注意:

  Java中的 Char 是一个字符,而不是一个字节,与 VC 的 WORD 长度一致;

  Java中的 Byte 是一个字节,与 C++ 中的 char 含义一致,而 VC 中的 BYTE 是无符号的char ;

  Java中的 long 长度为 8 ,而 VC 中的 long 长度为 4 ( C++ 中 short , long 的长度跟编译器的实现相关)。

Big-endian相关推荐

  1. byte endian(biglittle endian)

    1. 大小端的区别 little endian:把低位字节存放在内存的低位; // big endian:   将低位字节存放在内存的高位; 比如:0x1234,则12 就属于高位字节:34 属于低位 ...

  2. 字符编码简介 ANSI Unicode Unicode big endian UTF-8

    1. ASCII码 我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串.每一个二进制位(bit)有0和 1两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(byte) ...

  3. redis源码笔记-endian

    对于目标机是大端字节序的机器,进行字节码的转换,提供了16byte.32byte.64byte字节的转换.在intset\ziplist\zipmap三种数据结构中使用,使得不同字节序机器生成的rdb ...

  4. 关于endian的故事,big-endian和little-endian

    为什么80%的码农都做不了架构师?>>>    在各种计算机体系结构中,对于字节.字等的存储机制有所不同,因而引发了计算机通信领域中一个很重要的问题,即通信双方交流的信息单元(比特. ...

  5. c语言中.h文件中的宏定义,endian.h这个头文件里面的宏可以直接用么?

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 endian.h头文件中以宏的形式定义了大端字节序.小端字节序和混合字节序 #define __LITTLE_ENDIAN 1234 #define __ ...

  6. 大端(Big Endian)与小端(Little Endian)详解

    大端(Big Endian)与小端(Little Endian)简介 /// 1. 你从哪里来? 端模式(Endian)的这个词出自JonathanSwift书写的<格列佛游记>.这本书根 ...

  7. big and little endian

    总是容易搞混big endian 和 little endian,但是找到一篇文章,其解释让人耳目一新. 文章链接:http://www.cs.umd.edu/class/sum2003/cmsc31 ...

  8. big endian and little endian

    big endian(大端)和little endian(小端)表示机器对变量字节的存储顺序.big endian表示低地址存放最高有效字节,little endian表示低地址存放最低有效字节.这里 ...

  9. Endian Bitfiled

    Endianess是个比较tricky的问题,特别是当数据在不同类型间转换时. 先看看在一台32位的little-endian机器上,以下代码的行为: C代码   #include <stdio ...

  10. 字节序是什么?(大小端 Big endian Little endian)

    字节序,即字节在电脑中存放时的序列与输入(输出)时的序列是先到的在前还是后到的在前. 字节序是指多字节数据在计算机内存中存储或者网络传输时各字节的存储顺序. 常见序: Little endian: 将 ...

最新文章

  1. How to recover from 'programmers burnout(转)
  2. shapenet网络_GRNet网络:3D网格进行点云卷积,实现点云补全
  3. html中ng-src,angularjs – 在ng-src中使用{{}}绑定,但不会加载ng-src
  4. 机器学习笔记(十六)——EM算法概述
  5. 原生ajax请求的五个步骤
  6. mosquitto支持websocket的使用方法
  7. (32)FPGA米勒型状态机设计(三段式)(第7天)
  8. Php超出高度隐藏,html字符超出指定高度后省略显示_html/css_WEB-ITnose
  9. vasp 计算杨氏弹性_VASP计算-力学常数1
  10. java 日语文档翻译_日语文档怎么翻译?我来教会你日语翻译
  11. PHP实训笔记,Java实训笔记(八)之mysql
  12. 投资与创业:程序猿如何改变世界
  13. java重复执行方法_重复java方法
  14. 网站所在服务器查询方法
  15. Elasticsearch ILM 索引生命周期管理常见坑及避坑指南
  16. MSDC 4.3 接口规范(7)
  17. (a++) + (++a)
  18. HTML5中制作彩色圆环的代码,HTML5 五彩圆环Loading加载动画实现教程
  19. 蒸妙熏蒸,让脚部保养通经络
  20. Android一周时间早中晚排班表

热门文章

  1. 提升源代码安全管控,从源头保护敏感数据
  2. 飞信Fetion 开发资料及下载
  3. 出海现金贷还有未来吗?
  4. 单通道和多通道图像相关概念
  5. 计算相似度评价值体系:欧几里德距离和皮尔逊相关度
  6. 要想步入程序开发行列,就不得不知道的事情汇总
  7. 用个人电脑搭建服务器
  8. 领导力培训课程鱼龙混杂,还不如看这本经典领导力书籍来得实在!
  9. 华人占大半壁江山!CVPR 2021 目标检测论文大盘点(65篇论文)
  10. 人脸检测算法落地详解