网络字节序和主机字节序详解

我们都知道,如今的通讯方式已经趋向与多样化,异构通信(计算机软件(操作系统) +    计算机硬件(内核架构,ARM,x86)不同)也已经很普遍了,如,手机和电脑中的qq进行通信,,,

 

同时,在计算机设计之初,对内存中数据的处理也有不同的方式,(低位数据存储在低位地址处或者高位数据存储在低位地址处),然而,在通信的过程中(ISO/OSI模型和TCP/IP四层模型中),数据被一步步封装(然后加入信息首部),当传到目的段时,被一步步解封,然后获取数据

 

从上面我们可以看出,数据在传输的过程中,一定有一个标准化的过程,也就是说:从主机a到主机b进行通信,

a的固有数据存储-------标准化--------转化成b的固有格式

 

如上而言:a或者b的固有数据存储格式就是自己的主机字节序,上面的标准化就是网络字节序(也就是大端字节序)

 

a的主机字节序----------网络字节序 ---------b的主机字节序

 

 

主机字节序:

就是自己的主机内部,内存中数据的处理方式,可以分为两种:

  • 大端字节序是指一个整数的高位字节(32-31bit)存储在内存的低地址处,低位字节(0-7bit)存储在内存的高地址处。
  • 小端字节序是指一个整数的高位字节(32-31bit)存储在内存的高地址处,低位字节(0-7bit)存储在内存的低地址处。

现代PC大多采用小端字节序,所以小端字节序又被称为主机字节序。
大端字节序也称为网络字节序。

即使是同一台机器上的两个进程(比如一个由C语言,另一个由Java编写)通信,也要考虑字节序的问题(JVM采用大端字节序)。

 

但是,如何知道我们的主机是那一种的呢???这个我们可以通过程序来进行验证:

 

 
  1. <span style="font-size:18px;">#include <stdio.h>

  2. #include <arpa/inet.h>

  3.  
  4. int main(){

  5.  
  6. unsigned long a = 0x12345678;

  7. unsigned char *p = (unsigned char *)(&a);

  8.  
  9. printf("主机字节序:%0x %0x %0x %0x\n", p[0], p[1], p[2], p[3]);

  10.  
  11. unsigned long b = htonl(a); //将主机字节序转化成了网络字节序

  12.  
  13. p = (unsigned char *)(&b);

  14.  
  15. printf("网络字节序:%0x %0x %0x %0x\n", p[0], p[1], p[2], p[3]);

  16. return 0;

  17. } </span>

运行结果:

可以看到我的当前主机是:小端字节序

 

关于:htonl

 
  1. <span style="font-size:18px;">#include <arpa/inet.h>

  2.  
  3. uint32_t htonl(uint32_t hostlong);

  4.  
  5. uint16_t htons(uint16_t hostshort);

  6.  
  7. uint32_t ntohl(uint32_t netlong);

  8.  
  9. uint16_t ntohs(uint16_t netshort);</span>

 

h是主机host,n是网络net,l是长整形long,s是短整形short,所以上面这些函数还是很好理解的

 

 
  1. <span style="font-size:18px;">#include <stdio.h>

  2. #include <arpa/inet.h>

  3.  
  4. int main()

  5. {

  6. struct in_addr ipaddr;

  7. unsigned long addr = inet_addr("192.168.1.100");

  8. printf("addr = %u\n", ntohl(addr));

  9.  
  10. ipaddr.s_addr = addr;

  11. printf("%s\n", inet_ntoa(ipaddr));

  12. return 0;

  13. } </span>

运行结果:

值得注意的是:

in_addr_in   inet_addr(const char *strptr);

inet_addr的参数是一个:点分十进制字符串,返回的值为一个32位的二进制网络字节序的IPv4地址,不然的话就是:INADDR_NONE

而返回值为:in_addr_t:IPv4,一般为uint32_t

所以也可以定义为:unsigned long

 

char * inet_ntoa(struct in_addr inaddr);

参数是一个结构体,所以要调用必须先定义一个结构体。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值