引言:在进行网络通信时是否需要进行字节序转换?

相同字节序的平台在进行网络通信时可以不进行字节序转换,但是跨平台进行网络数据通信时必须进行字节序转换。原因如下:网络协议规定接收到得第一个字节是高字节,存放到低地址,所以发送时会首先去低地址取数据的高字节。小端模式的多字节数据在存放时,低地址存放的是低字节,而被发送方网络协议函数发送时会首先去低地址取数据(想要取高字节,真正取得是低字节),接收方网络协议函数接收时会将接收到的第一个字节存放到低地址(想要接收高字节,真正接收的是低字节),所以最后双方都正确的收发了数据。而相同平台进行通信时,如果双方都进行转换最后虽然能够正确收发数据,但是所做的转换是没有意义的,造成资源的浪费。而不同平台进行通信时必须进行转换,不转换会造成错误的收发数据,字节序转换函数会根据当前平台的存储模式做出相应正确的转换,如果当前平台是大端,则直接返回不进行转换,如果当前平台是小端,会将接收到得网络字节序进行转换。  下面对一些概念做下介绍:

一、大端、小端
"大端"和"小端"表示多字节值的哪一端存储在该值的起始地址处;小端存储在起始地址处,即是小端字节序;大端存储在起始地址处,即是大端字节序;
或者说:
1.小端法(Little-Endian)就是低位字节排放在内存的低地址端(即该值的起始地址),高位字节排放在内存的高地址端;
2.大端法(Big-Endian)就是高位字节排放在内存的低地址端(即该值的起始地址),低位字节排放在内存的高地址端;
举个简单的例子,对于整型数据0x12345678,它在大端法和小端法的系统中,各自的存放方式如下图1所示:


二、网络字节序
网络上传输的数据都是字节流,对于一个多字节数值,在进行网络传输的时候,先传递哪个字节?也就是说,当接收端收到第一个字节的时候,它将这个字节作为高位字节还是低位字节处理,是一个比较有意义的问题;
UDP/TCP/IP协议规定:把接收到的第一个字节当作高位字节看待,这就要求发送端发送的第一个字节是高位字节;而在发送端发送数据时,发送的第一个字节是该数值在内存中的起始地址处对应的那个字节,也就是说,该数值在内存中的起始地址处对应的那个字节就是要发送的第一个高位字节(即:高位字节存放在低地址处);由此可见,多字节数值在发送之前,在内存中因该是以大端法存放的;
所以说,网络字节序是大端字节序;
比如,我们经过网络发送整型数值0x12345678时,在80X86平台中,它是以小端发存放的,在发送之前需要使用系统提供的字节序转换函数htonl()将其转换成大端法存放的数值;如下图2所示: 
三、字节序测试
不同CPU平台上字节序通常也不一样,下面这个简单的代码可以测试不同平台上的字节序:
#include <stdio.h>
#include <netinet/in.h>
int main(int argc,char** argv)
{
  int num = 0x12345678;
  unsigned char* pc = (unsigned char*)(&num);
  printf("local order:\n");
  printf("[0]: 0x%X addr:%u\n", pc[0], &pc[0]);
  printf("[1]: 0x%X addr:%u\n", pc[1], &pc[1]);
  printf("[2]: 0x%X addr:%u\n", pc[2], &pc[2]);
  printf("[3]: 0x%X addr:%u\n", pc[3], &pc[3]);
  num = htonl(num);
  printf("htonl order:\n");
  printf("[0]: 0x%X addr:%u\n", pc[0], &pc[0]);
  printf("[1]: 0x%X addr:%u\n", pc[1], &pc[1]);
  printf("[2]: 0x%X addr:%u\n", pc[2], &pc[2]);
  printf("[3]: 0x%X addr:%u\n", pc[3], &pc[3]);
  return 0;
}
SPARC平台上的输出:
local order:
[0]: 0x12 addr:4290770212 //高位字节存放在低地址处,则是大端法;
[1]: 0x34 addr:4290770213
[2]: 0x56 addr:4290770214
[3]: 0x78 addr:4290770215 //低位字节存放在高地址处;
htonl order:
[0]: 0x12 addr:4290770212 //由此看出,主机字节序与网络字节一样;
[1]: 0x34 addr:4290770213
[2]: 0x56 addr:4290770214
[3]: 0x78 addr:4290770215
X86平台上的输出:
local order:
[0]: 0x78 addr:4289157020 //低位字节存放在低地址处,则是小端法;
[1]: 0x56 addr:4289157021
[2]: 0x34 addr:4289157022
[3]: 0x12 addr:4289157023 //高位字节存放在高地址处;
htonl order:
[0]: 0x12 addr:4289157020 //由此看出,主机字节序与网络字节不一样;
[1]: 0x34 addr:4289157021
[2]: 0x56 addr:4289157022
[3]: 0x78 addr:4289157023
INTEL平台上的输出:
local order:
[0]: 0x78 addr:1245044    //低位字节存放在低地址处,则是小端法;
[1]: 0x56 addr:1245045
[2]: 0x34 addr:1245046
[3]: 0x12 addr:1245047    //高位字节存放在高地址处;
htonl order:
[0]: 0x12 addr:1245044    //由此看出,主机字节序与网络字节不一样;
[1]: 0x34 addr:1245045
[2]: 0x56 addr:1245046
[3]: 0x78 addr:1245047

网络通信时字节序转换原理与网络字节序、大端和小端模式 .相关推荐

  1. 网络通信之 字节序转换原理与网络字节序、大端和小端模式

    一.在进行网络通信时是否需要进行字节序转换? 相同字节序的平台在进行网络通信时可以不进行字节序转换,但是跨平台进行网络数据通信时必须进行字节序转换. 原因如下:网络协议规定接收到得第一个字节是高字节, ...

  2. 大端和小端传输字节序

    大端和小端 在计算机中是以字节为单位,每一个地址对应一个字节,一个字节8bit.在C中,除了8bit的char以外,还有16bit的short,32位的int,64位long,当然具体要由编译器决定, ...

  3. 大端模式小端模式 主机序网络序

    1. 主机序 不同的CPU有不同的字节序类型这些字节序是指整数在内存中保存的顺序,这个叫做主机序.最常见的有两种: 1.         Little endian:将低序字节存储在起始地址. 即小端 ...

  4. 大端模式小端模式、主机序网络序、入栈地址高低问题

    一.大端模式&小端模式 所谓的"大端模式",是指数据的低位(就是权值较小的后面那几位)保存在内存的高地址中,而数据的高位,保存在内存的低地址中,这样的存储模式有点儿类似于把 ...

  5. 大端模式、小端模式、高字节序、低字节序、MSB、LSB

    摘要:你知道内存是怎么读取数据的吗?知道数据是怎么一个一个字节发送的吗?是低字节先发还是高字节先发?是bit0先发还是bit7先发?是从低地址开始读还是从高地址开始读?看完本篇比应该就明白了~ 内存的 ...

  6. 字节顺序:大端模式 和 小端模式

    字节顺序有"大端模式" 和 "小端模式" 两种. 一.字节顺序只是对内置数据类型而言. 例如对于一整型(int,int 是内置数据类型)数,比如 0x12345 ...

  7. 【Linux网络编程】大端模式和小端模式

    00. 目录 文章目录 00. 目录 01. 概述 02. 示例分析 03. 优缺点 04. 数组存储 05. 测试机器模式 07. 附录 01. 概述 大端模式(Big-endian):高位字节排放 ...

  8. 网络传输大端序_大端、小端与网络字节序

    大端(Big-Endian),小端(Little-Endian)以及网络字节序的概念在编程中经常会遇到.网络字节序(Network Byte Order)一般是指大端(Big-Endian,对大部分网 ...

  9. linux网络编程之网络字节序、主机字节序、大端、小端

    1.主机字节序介绍 不同的CPU有不同的字节序类型 这些字节序是指整数在内存中保存的顺序 这个叫做主机字节序,存储方式有2种 1).大端模式 大端模式(Big-Endian)就是高位字节排放在内存的低 ...

最新文章

  1. 关于tcp、http可能你想知道的那些事
  2. IOS7笔记-6、控制器多态性、导航控制器、选项卡栏控制器
  3. jquery页面加载ajax请求,jquery ajax 加载页面
  4. Nginx 的常用命令
  5. 求解两个经纬点之间的距离和角度(mm级精度)
  6. sparkstreaming消费receive
  7. 基于Springboot+Vue实现前后端分离进销存管理系统
  8. 三洋p6系列伺服电机说明书_苏州发那科伺服电机修理刹不住
  9. 如何用计算机打出平方,如何用电脑打出平方?平方米符号输入方法介绍
  10. 提莫攻击 findPoisonedDuration
  11. mongo 手册阅读笔记
  12. 限时活动|凭徽章领披萨大奖,玩转Moonbeam治理论坛
  13. 安卓日志系统初探(带你了解Android日志系统的概貌)
  14. NETDMIS5.0对有CAD模型的工件运用“3-2-1”法建立零件坐标2023
  15. 一文实现:在python中调用matlab程序,保姆级安装windows环境下的matlab.engine教程
  16. kali linux 中的网卡驱动,kali linux 安装Realtek 8812AU网卡驱动
  17. lacp - 链路汇聚控制协议
  18. Ubuntu下批量重命名图片并将路径写入txt文件
  19. Leetcode52.Maximum Subarray(贪心与分治)
  20. 关于电脑BIOS解密,如何解密问题?

热门文章

  1. IDLpython学习——实现根据有经纬度坐标的excel/csv表格提取相应影像的像元值
  2. 互联网拓扑是怎样构成的?又代表了什么?
  3. warning: CRLF will be replaced by LF in 出现的原因和解决办法
  4. 笑着离开惠普读书笔记
  5. java+selenium的入门 案例 selenium包 谷歌驱动包 火狐驱动包 IE驱动包 (一)
  6. golang触发gc的时机
  7. spark sql教程_如何使用Spark SQL:动手教程
  8. 《西瓜书》阅读笔记——第一章
  9. 论文脚注上方横线不是顶格的怎么办?
  10. MySql字段名为关键字,怎么办?