网络字节序

  • 网络字节序
    • 1、网络字节序 (Network Byte Order)和本机转换
    • 2、字节序转换函数

网络字节序

1、网络字节序 (Network Byte Order)和本机转换

1、大端、小端字节序
“大端”和”小端”表示多字节值的哪一端存储在该值的起始地址处;小端存储在起始地址处,即是小端字节序;大端存储在起始地址处,即是大端字节序;具体的说:

  • ①大端字节序(Big Endian):最高有效位存于最低内存地址处,最低有效位存于最高内存处;
  • ②小端字节序(Little Endian):最高有效位存于最高内存地址,最低有效位存于最低内存处。

如下图:当以不同的存储方式,存储数据为0x12345678时:

网络字节序:大端字节序
网络上传输的数据都是字节流,对于一个多字节数值,在进行网络传输的时候,先传递哪个字节?也就是说,当接收端收到第一个字节的时候,它将这个字节作为高位字节还是低位字节处理,是一个比较有意义的问题:

UDP/TCP/IP协议规定:把接收到的第一个字节当作高位字节看待,这就要求发送端发送的第一个字节是高位字节;而在发送端发送数据时,发送的第一个字节是该数值在内存中的起始地址处对应的那个字节,也就是说,该数值在内存中的起始地址处对应的那个字节就是要发送的第一个高位字节

所以:网络字节序就是大端字节序, 有些系统的本机字节序是小端字节序, 有些则是大端字节序, 为了保证传送顺序的一致性, 所以网际协议使用大端字节序来传送数据

如何证明自己的机器采用了哪种字节顺序:

/* 确定你的电脑是大端字节序还是小端字节序 */
#include <stdio.h>int check1()
{int i = 1; //1在内存中的表示: 0x00000001char *pi = (char *)&i; //将int型的地址强制转换为char型return *pi == 0; //如果读取到的第一个字节为1,则为小端法,为0,则为大端法
}int main()
{if (check1() == 1)printf("big\n");elseprintf("little\n");return 0;
}第二种方法,我们用联合结构解决,其本质差异不大
/* 确定你的电脑是大端字节序还是小端字节序 */
#include <stdio.h>int check2()
{union test {char ch;int i;}test0;test0.i = 1;return test0.ch == 0;
}
int main()
{if (check1() == 1)printf("big\n");elseprintf("little\n");return 0;
}

因为联合结构中的变量共用一块存储空间,所以ch和i拥有同一个地址:

对本例中的联合结构,我们对它求sizeof(test0),会发现它的大小为4,取了int 的大小。关于union,我们说了,它里边的变量共用一块存储空间,但是它的大小并不总是其中最大的变量所占的空间,还需要考虑对齐!比如:union test1 {char[5];int i;}它的大小就是 8 了!

2、字节序转换函数

字节序转换函数

 #include <arpa/inet.h>//将主机字节序转换为网络字节序unit32_t htonl (unit32_t hostlong);unit16_t htons (unit16_t hostshort);//将网络字节序转换为主机字节序unit32_t ntohl (unit32_t netlong);unit16_t ntohs (unit16_t netshort);说明:h -----host;n----network ;s------short;l----long。
htons()--"Host to Network Short"
htonl()--"Host to Network Long"
ntohs()--"Network to Host Short"
ntohl()--"Network to Host Long"

为什么在数据结构 struct sockaddr_in 中, sin_addr 和 sin_port 需要转换为网络字节顺序,而sin_family 需不需要呢?

答案是: sin_addrsin_port 分别封装在包的 IPUDP 层。因此,它们必须要 是网络字节顺序。但是 sin_family 域只是被内核 (kernel) 使用来决定在数 据结构中包含什么类型的地址,所以它必须是本机字节顺序。同时, sin_family 没有发送到网络上,它们可以是本机字节顺序。

IP 地址如何处理:地址转换函数

IP地址的三种表示格式及在开发中的应用

  • 1)点分十进制表示格式

  • 2)网络字节序格式

  • 3)主机字节序格式

用IP地址127.0.0.1为例:

   第一步   127   .     0     .     0      .    1   把IP地址每一部分转换为8位的二进制数。第二步 01111111     00000000     00000000     00000001      =   2130706433   (主机字节序)然后把上面的四部分二进制数从右往左按部分重新排列,那就变为:第三步 00000001     00000000     00000000    01111111        =   16777343        (网络字节序)

1、函数inet_addr(),将IP地址从 点数格式转换成无符号长整型。使用方法如下:

函数原型

in_addr_t inet_addr(const char *cp);

转换网络主机地址(点分十进制)为网络字节序二进制值,

  • cp代表点分十进制的IP地址,如1.2.3.4
  • 如果参数 char *cp 无效则返回-1(INADDR_NONE),
  • 但这个函数有个缺点:在处理地址为255.255.255.255时也返回-1,虽然它是一个有效地址,但inet_addr()无法处理这个地址。

使用

ina.sin_addr.s_addr = inet_addr("132.241.5.10");

现在你可以将IP地址转换成长整型了。有没有其相反的方法呢? 它可以将一个in_addr结构体输出成点数格式?

2、你就要用到函数 inet_ntoa()(“ntoa"的含义是"network to ascii”),就像这样:
函数原型

char* inet_ntoa(struct in_addr in);

参数:

  • in代码in_addr的结构体,其结构体如下:
struct in_addr
{union {struct { UCHAR s_b1,s_b2,s_b3,s_b4; } S_un_b;struct { USHORT s_w1,s_w2; } S_un_w;ULONG S_addr;} S_un;
};

使用

SOCKADDR_IN sock;
sock.sin_family = AF_INET;
//将字符串转换为in_addr类型
sock.sin_addr.S_un.S_addr =  inet_addr("192.168.1.111");
sock.sin_port = htons(5000);//将in_addr类型转换为字符串
printf("inet_ntoa ip = %s\n",inet_ntoa(sock.sin_addr));结果输出:
inet_ntoa ip = 192.168.1.111

注意:
inet_ntoa()将结构体in_addr作为一个参数,不是长整形。同样需要注意的是它返回的是一个指向一个字符的 指针。它是一个由inet_ntoa()控制的静态的固定的指针,所以每次调用 inet_ntoa(),它就将覆盖上次调用时所得的IP地址。例如:

char *a1, *a2;……a1 = inet_ntoa(ina1.sin_addr); /* 这是198.92.129.1 */a2 = inet_ntoa(ina2.sin_addr); /* 这是132.241.5.10 */printf("address 1: %s\n",a1);printf("address 2: %s\n",a2);输出如下:address 1: 132.241.5.10address 2: 132.241.5.10

计算机网络——网络字节序(大端字节序(Big Endian)\小端字节序(Little Endian))相关推荐

  1. 小端字节序与大端字节序

    端模式分为:小端字节序和大端字节序,也就是字节在内存中的顺序. 小端字节序:低字节存于内存低地址:高字节存于内存高地址.如一个long型数据0x12345678 0x0029f458 0x78 0x0 ...

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

    端模式分为:小端字节序和大端字节序,也就是字节在内存中的顺序. 需要注意的是,对于数据来说,高字节是指最高位字节,即左边第一位! 小端字节序:低字节存于内存低地址:高字节存于内存高地址.如一个long ...

  3. 大端字节序小端字节序(网络字节序主机字节序)

    大端字节序:整数的高位字节存储在内存的低地址处,低字节存储在内存的高地址处. 小端字节序:整数的高位字节存储在内存的高地址处,低字节存储在内存的低地址处. 一般pc大多采用小端字节序,也称为主机字节序 ...

  4. 大端字节序与小端字节序 (网络字节序与主机字节序)

    大端字节序与小端字节序 1. 简介 2. 判断机器字节序(C/C++) 3. 主机字节序与网络字节序的转换 4. IP地址与网络字节序的转换 1. 简介 字节序分为大端字节序(big endian)和 ...

  5. java 大端字节序_理解字节序 大端字节序和小端字节序

    以下内容参考了 http://www.ruanyifeng.com/blog/2016/11/byte-order.html https://blog.csdn.net/yishengzhiai005 ...

  6. 【转】理解字节序 大端字节序和小端字节序

    转自:https://www.cnblogs.com/gremount/p/8830707.html 以下内容参考了 http://www.ruanyifeng.com/blog/2016/11/by ...

  7. 字节序(小端字节序与大端字节序)

    概念: 字节序是指多字节数据在计算机内存中存储或者网络传输时各字节的存储顺序. 常见的字节序有: Little endian(小端字节序):将低序字节存储在起始地址: Big endian(大端字节序 ...

  8. 字节序、大端字节序(Big Endian)、小端字节序(Little Endian)总结

    什么是字节序? 字节序,简单来说,指的是 超过一个字节的数据类型在内存中存储的顺序 有几种字节序? 大端字节序(Big Endian) 高位字节数据存放在内存低地址处,低位字节数据存放在内存高地址处. ...

  9. 如何确定CPU是大端字节序还是小端字节序?

    大端字节序:高字节存放在低地址,低字节存放在高低址 小端字节序:低字节存放在高低址,高字节存放在低地址 大小端字节顺序它是CPU的属性,所哟不同的CPU的大小端字节顺序也不同,移植的时候需要先判断当前 ...

最新文章

  1. 漏答题、偏科、多次复读,30 位互联网大佬考上啥大学了?
  2. Html 教程 (5) 表格标签
  3. Mozilla发布2015年度报告:搜索合作成营收大头
  4. 使用Subversion版本标识符
  5. 超全荧光定量PCR应用常见问题
  6. 用最简单的方式训练史上最强ResNet-50,性能超过魔改结构的ResNeSt
  7. Little Sub and Apples
  8. DOS 批量修改文件名
  9. 披荆斩棘:饿了么业务架构的演进之路
  10. pip更新命令_如何批量更新电脑中的python包?
  11. 孪生神经网络_驾驶习惯也能识人?基于时空孪生神经网络的轨迹识别
  12. 全网最强最细postman接口测试教程(一)
  13. wingdings字体符号在哪_Wingdings特殊字符及符號對照表 | 學步園
  14. linux通过修改/etc/hosts文件 添加IP地址与域名的映射
  15. Codeforces - Chloe and pleasant prizes
  16. 《地理天机一贯 》   聚宝馆手抄珍稀古籍分享
  17. 课后作业十(定点计算)
  18. 起点:如何成为一名黑客?
  19. pg数据库数据量很小但是data目录很大的排查思路
  20. 仅改变rowspan背景_山西耗资10亿的小镇,人称长治“小周庄”,距市中心仅16公里...

热门文章

  1. 【C++】——快速排序(前后指针,挖坑法,快慢指针法)
  2. cvs在更新程序的时候颜色是代表什么意思?
  3. springBoot整合mybatis_plus时候,出现Unknown column ‘grade_id‘ in ‘field list‘
  4. 杂谈:用户的搜索意图(intention of SE users)
  5. thinkphp5消息队列(think-queue)
  6. PCR406-ASEMI代理长电原厂单向可控硅PCR406
  7. 云服务器连接手机本地文件夹,云服务器连接手机本地文件
  8. leetcode LCP2 分式化简(C++)
  9. GPS 校验和 代码_YBS-YFQ-100K真空压力校验台气压校验压力台表压力变送器
  10. 写html网页注册机,动态网页编辑器(含注册机)