Part 1: htons函数具体解释
     在Linux和Windows网络编程时需要用到htons和htonl函数,用来将主机字节顺序转换为网络字节顺序。

在Intel机器下,执行以下程序

int main()
...{
   printf("%d /n",htons(16));
      return 0;
}
得到的结果是4096,初一看感觉很怪。

解释如下,数字16的16进制表示为0x0010,数字4096的16进制表示为0x1000。 由于Intel机器是小尾端,存储数字16时实际顺序为1000,存储4096时实际顺序为0010。因此在发送网络包时为了报文中数据为0010,需要经过htons进行字节转换。如果用IBM等大尾端机器,则没有这种字节顺序转换,但为了程序的可移植性,也最好用这个函数。

另外用注意,数字所占位数小于或等于一个字节(8 bits)时,不要用htons转换。这是因为对于主机来说,大小尾端的最小单位为字节(byte)。

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

LE little-endian 
最符合人的思维的字节序 
地址低位存储值的低位 
地址高位存储值的高位 
怎么讲是最符合人的思维的字节序,是因为从人的第一观感来说 
低位值小,就应该放在内存地址小的地方,也即内存地址低位 
反之,高位值就应该放在内存地址大的地方,也即内存地址高位

BE big-endian 
最直观的字节序 
地址低位存储值的高位 
地址高位存储值的低位 
为什么说直观,不要考虑对应关系 
只需要把内存地址从左到右按照由低到高的顺序写出 
把值按照通常的高位到低位的顺序写出 
两者对照,一个字节一个字节的填充进去

例子:在内存中双字0x01020304(DWORD)的存储方式

内存地址 
4000 4001 4002 4003 
LE 04 03 02 01 
BE 01 02 03 04

例子:如果我们将0x1234abcd写入到以0x0000开始的内存中,则结果为
      big-endian  little-endian
0x0000  0x12      0xcd
0x0001  0x23      0xab
0x0002  0xab      0x34
0x0003  0xcd      0x12
x86系列CPU都是little-endian的字节序.

网络字节顺序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用big endian排序方式。

为了进行转换 bsd socket提供了转换的函数 有下面四个
htons 把unsigned short类型从主机序转换到网络序
htonl 把unsigned long类型从主机序转换到网络序
ntohs 把unsigned short类型从网络序转换到主机序
ntohl 把unsigned long类型从网络序转换到主机序

在使用little endian的系统中 这些函数会把字节序进行转换 
在使用big endian类型的系统中 这些函数会定义成空宏

同样 在网络程序开发时 或是跨平台开发时 也应该注意保证只用一种字节序 不然两方的解释不一样就会产生bug.

注:
1、网络与主机字节转换函数:htons ntohs htonl ntohl (s 就是short l是long h是host n是network)
2、不同的CPU上运行不同的操作系统,字节序也是不同的,参见下表。
处理器    操作系统    字节排序
Alpha    全部    Little endian
HP-PA    NT    Little endian
HP-PA    UNIX    Big endian
Intelx86    全部    Little endian <-----x86系统是小端字节序系统
Motorola680x()    全部    Big endian
MIPS    NT    Little endian
MIPS    UNIX    Big endian
PowerPC    NT    Little endian
PowerPC    非NT    Big endian  <-----PPC系统是大端字节序系统
RS/6000    UNIX    Big endian
SPARC    UNIX    Big endian
IXP1200 ARM核心    全部    Little endian

Part 3: 模拟htonl、ntohl、htons、ntohs函数实现
--------------------------------------------------------------------------------
今天在如鹏网里讨论htonl、ntohl在不同机器的区别,特意模拟了htonl、ntohl、htons、ntohs函数实现。
实现如下:
typedef unsigned short int uint16;

typedef unsigned long int uint32;

// 短整型大小端互换

#define BigLittleSwap16(A)  ((((uint16)(A) & 0xff00) >> 8) | /

(((uint16)(A) & 0x00ff) << 8))

// 长整型大小端互换

#define BigLittleSwap32(A)  ((((uint32)(A) & 0xff000000) >> 24) | /

(((uint32)(A) & 0x00ff0000) >> 8) | /

(((uint32)(A) & 0x0000ff00) << 8) | /

(((uint32)(A) & 0x000000ff) << 24))

// 本机大端返回1,小端返回0

int checkCPUendian()

{

union{

unsigned long int i;

unsigned char s[4];

}c;

c.i = 0x12345678;

return (0x12 == c.s[0]);

}

// 模拟htonl函数,本机字节序转网络字节序

unsigned long int HtoNl(unsigned long int h)

{

// 若本机为大端,与网络字节序同,直接返回

// 若本机为小端,转换成大端再返回

return checkCPUendian() ? h : BigLittleSwap32(h);

}

// 模拟ntohl函数,网络字节序转本机字节序

unsigned long int NtoHl(unsigned long int n)

{

// 若本机为大端,与网络字节序同,直接返回

// 若本机为小端,网络数据转换成小端再返回

return checkCPUendian() ? n : BigLittleSwap32(n);

}

// 模拟htons函数,本机字节序转网络字节序

unsigned short int HtoNs(unsigned short int h)

{

// 若本机为大端,与网络字节序同,直接返回

// 若本机为小端,转换成大端再返回

return checkCPUendian() ? h : BigLittleSwap16(h);

}

// 模拟ntohs函数,网络字节序转本机字节序

unsigned short int NtoHs(unsigned short int n)

{

// 若本机为大端,与网络字节序同,直接返回

// 若本机为小端,网络数据转换成小端再返回

return checkCPUendian() ? n : BigLittleSwap16(n);

}

本文来自CSDN博客,转载请标明出处:http://blog.csdn.Net/fjiale/archive/2010/06/25/5693509.aspx

主机字节序与网络字节序的转换函数:htonl、ntohl、htons、ntohs相关推荐

  1. TCP/IP,网络字节序与本地转换,Linux提供的转换函数htonl,htons等,sock_addr的数据结构与内容

    TCP/IP,网络字节序与本地转换,Linux提供的转换函数htonl,htons等,sock_addr的数据结构与内容 一.网络字节序存储方式: 小端存储:高位存放高地址,0x12345678的小段 ...

  2. linux网络编程一:主机字节序与网络字节序的的判断

     linux网络编程一:主机字节序与网络字节序的的判断(1)现代CPU的累加器一次能装载至少4字节(32位),即一个整数.那么这4字节在内存中排列的顺序将影响它被累加器装载成的整数值,这就是字节序问题 ...

  3. 【Linux】主机字节序和网络字节序

    (一)问题提出:为什么要有主机字节序和网络字节序的存在? 现在大多数PC机器都是小端字节序(小端存储),也称为主机字节序:但不排除有大端PC机器的存在. 若在两台字节序不同的主机上传输数据时,接收端将 ...

  4. 主机字节序与网络字节序的转换函数:htonl、ntohl、htons、ntohs【转】

    (转自:https://blog.csdn.net/kulala082/article/details/53431473) Part 1: htons函数具体解释 在Linux和Windows网络编程 ...

  5. 字节序 主机字节序与网络字节序互相转换

    目录 1.什么是字节序? 2.字节序分类 3.为什么要有大端字节序和小端字节序? 4.主机字节序和网络字节序 5.主机字节序与网络字节序的转换 6.怎么判断自己的主机是小端字节序还是大端字节序呢? 7 ...

  6. 主机字节序和网络字节序

    1.大端字节序和小端字节序: 大端字节序存储时值的高位存储在较小的地址,值的低位存储在较大的地址. 小端字节序存储时值的高位存储在较大的地址,值的低位存储在较小的地址. 以0x12345678为例: ...

  7. Linux---主机字节序与网络字节序

    现在的CPU累加器一次能够装载至少4个字节的一个整数,那么字节在内存中的排列顺序不同,导致累加器使用的结果不同,这就是字节序问题 . 例如: 我们存储一个int类型的数字:int a = 1; 主机字 ...

  8. 什么是字节序(端序、低端字节序、高端字节序、网络字节序)

    前言 一个内容为12(字符串)的文本文件,它的第一个字节是什么(小端序)?如果你的回答是0x32,那你真的应该好好理解下字节序了.如下图所示,我这里的正确答案是0x31.当然如果你的回答是不一定,这似 ...

  9. 本地字节序和网络字节序

    本地字节序和网络字节序 字节序指不同的CPU访问内存中多字节数据的时候,存在大小端的问题,并且一定是访问多字节数据的时候才会存在大小端的问题,如果CPU访问的是字符串,则不存在大小端的问题: 那么如何 ...

最新文章

  1. 织梦 百度sitemap制作教程
  2. 初窥wireshark fiddler等抓包工具及部分实现分析
  3. python葡萄酒数据集_利用python分析红葡萄酒数据
  4. ssl2645-线段树练习2【线段树】
  5. 【C语言进阶深度学习记录】十 C语言中:struct的柔性数组和union分析
  6. 自制 移动端 纯原生 Slider滑动插件
  7. eclipse安装选择清华镜像
  8. Visio绘图工具,“连接线”命令使用方法
  9. 可视对讲网络协议转换器怎么使用,协议转换器使用方法详细介绍
  10. IntelliJ Idea 下Png图片打开方式导致编码报错
  11. WIN10版本安装JDK
  12. GBase 8s SQL 指南:教程———3编写SELECT语句
  13. Ultimate Email Toolkit:16种出色的电子邮件工具
  14. 传统功能型产品经理,正在被淘汰?
  15. selenium不打开浏览器进行自动化操作
  16. 移动硬盘插电脑没反应
  17. 华为新品手机发布会全程回顾:AI加持下的十大创新
  18. 高仿小刀娱乐网系统源码+积分功能+前台投稿
  19. TensorFlow解决MNIST数字识别问题
  20. LaTeX 清理缓存文件脚本

热门文章

  1. pom里配置阿里云仓库
  2. java生成PDF,并下载到本地
  3. C#中字节数组(byte[])和字符串相互转换
  4. RAID磁盘阵列、mdadm、群晖软RAID
  5. C++HANDLE的理解
  6. 创建Springboot项目、java项目遇到的问题
  7. Mentor Graphics Calibre 2017.1 Linux 1DVD寄生參數萃取
  8. Python学习笔记(八)—切片(slicing)
  9. R语言 数据正态化+标准化
  10. java Date与 double 互转