网络传输中遇到的字节序问题

因为本人最近做的项目是路由器和交换机管理平台的开发,所以经常会遇到在一台路由器上测试没有任何问题,但是在另一台设备上测试就出现了问题的现象,最后发现还是字节序的问题,虽然对字节序的问题每次都很重视,但是总是在开发中遗漏或者忽略,字节序问题真是令人防不胜防。究其根本原因,一方面是因为自己对字节序的理解还停留在表面上,另一方面可能还是开发经验不足吧,呵呵。

在网上看到了许多讲字节序的文章,大部分都讲到了字节序的基本含义,大家一看也都明白字节序是怎么回事,但是在具体开发过程中还是总想不到或者时刻注意着却还是一不小心就出现了问题,可能还是理解的不够透彻,下面我就讲一下我自己的理解,基本的定义还是参考字节序的定义,里面加了一些自己的理解,我觉得这样好理解一些,希望我的讲解能让大家对字节序有更深的理解一些或者是更容易理解吧,高手勿喷,多多包涵,有不当的地方请指出,大家共同进步。

首先还是老生常谈介绍一下字节序的含义:

字节序称端序,端序最早是从格列佛游记中提到的,小人国的内战就源于吃鸡蛋时是从大端(Big-Endian)开始吃还是从小端(Little-Endian)开始吃,大端就是鸡蛋的圆头,小端就是鸡蛋的尖头。用在数据里面也就是高位数据是大大端,低位数据是小端,如0x1234,12是高字节数据,所以就是大端,34是低字节数据,所以就是小端。

    通过上面的讲解,大家应该对大端和小端有了了解,那么在商业领域也有一些CPU厂家,有些厂家觉得存取数据应该从大端开始,比如PowerPC、Motorola,有些厂家就觉得应该从小端开始,比如Intel、AMD。那么从大端开始存取数据和从小端开始存取数据有什么不一样呢,下面就给大家介绍一下:

    稍微对字节序有些了解的同学都知道大端字节序和小端字节序的基本区别,这里顺便提一下:

    大端字节序(Big-Endian):高地址内存单元存低字节数据,低地址内存单元存高字节数据

    小端字节序(Little-Endian):高地址内存单元存高字节数据,低地址内存单元存低字节数据

    两者正好相反,那么是怎么造成这种情况的呢,先给大家说一个基本知识,大家在申请内存空间的时候,不管是栈内存还是堆内存,申请内存以后内存的首地址都指向这段内存的最低字节单元,对这段内存进行操作也是使用内存的首地址进行操作的。

    现在首先说明大端环境下数据的存取情况,假如现在有一个32位整数0x12345678,现在将它存进一个4字节内存中,内存首地址为ptr,因为上面说过了大端字节序上存取数据都是从高字节数据开始的,所以,这里先把12开始存到ptr指向的内存单元0,接着取34,将34存到ptr+1的内存单元中,依次存完,这样就把0x12345678存到了这一个4字节内存中了,低字节数据存在4字节内存的高内存地址单元,高字节数据存在4字节内存的低内存地址单元

    在小端环境下数据的存取情况,依旧是将32位整数0x12345678存进一个4字节内存中,内存首地址是ptr(上面已经讲过,内存首地址都是在低地址的,任何编译器都是这样做的),因为上面已经说过小端字节序上存取数据是从低字节数据开始的,所以这里就先把78存到ptr指向的内存单元0,接着取56,将56存到ptr+1的内存单元中,依次存完,这样就把0x12345678存到了这一个4字节内存中了,低字节数据存在4字节内存的低内存地址单元,高字节数据存在4字节内存的高内存地址单元。

    但是其实存取数据不像上面讲的一个字节一个字节的存取的,其实在CPU上有数据总线和控制总线,在32位CPU上,一个时钟周期就把这32位数据存取完了。大家可以想象32根数据总线和内存相连(大端和小端上不差别),分配数据总线都是先把数据给第一根总线,第一根总线总是和低地址的低位比特相连,在大端设备上数据是从高字节数据开始的,所以就先把高字节数据的8位给了1-7的这八根数据线,剩下的依次分配,最后在一个时钟周期内把这32位数据存到了内存里,这样造成了高字节数据存在低地址内存单元,低字节数据存在高地址内存单元。

    而在小端设备上正好相反,数据是从低字节数据开始的,所以就把低字节数据的8位给了1-7这8根数据线,剩下的依次分配,最后在一个时钟周期内把这32位数据存到了内存里,这样就造成了高字节数据存在高地址内存单元,低字节数据存在低地址内存单元。

    大家在进行网络编程中,发送数据的时候数据使用的数据类型一定要和接收数据时数据使用的数据类型一样,这样才不会出现字节序的问题,如果不一样就有可能出现字节序的问题,小端字节序上肯定是没问题的,但在大端上就有可能了,大家还需要注意一点,字节序问题只会出现在涉及指针操作中,单纯的赋值是不会出现字节序的问题的,比如

int a = 0x12345678;

short b;

b = a;

这种情况是不会出现字节序的问题的;

但是下面这种就有可能了

int a = 0x12345678;

short *ptr;

int b;

prt = (short *)&a;

b =*ptr;

    

    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值