您当前的位置: 首页 >  Java

phymat.nico

暂无认证

  • 1浏览

    0关注

    1967博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

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

phymat.nico 发布时间:2015-01-28 14:00:29 ,浏览量:1

 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  

关注
打赏
1659628745
查看更多评论
立即登录/注册

微信扫码登录

0.0447s