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

计算机网络——网络字节序(大端字节序(Big Endian)\小端字节序(Little Endian))网络字节序网络字节序 1 网络字节序 NetworkByteO 和本机转换 2 字节序转换函数网络字节序 1 网络字节序 NetworkByteO 和本机转换 1 大端 小端字节序 大端 和 小端 表示多字节值的哪一端存储在该值的起始地址处 小端存储在起始地址处 即是小端字节序 大端存储在起始地址处 即是大端字节序 具体的说 大端字节序 BigEndian 最高有效位存于最低内存地址处 最低有效位存于最高内存处 小端字节序 LittleEndian 最高有效位

网络字节序

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

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

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

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

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

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

/* 确定你的电脑是大端字节序还是小端字节序 */ #include  
     int check1() { 
    int i = 1; //1在内存中的表示: 0x00000001 char *pi = (char *)&i; //将int型的地址强制转换为char型 return *pi == 0; //如果读取到的第一个字节为1,则为小端法,为0,则为大端法 } int main() { 
    if (check1() == 1) printf("big\n"); else printf("little\n"); return 0; } 第二种方法,我们用联合结构解决,其本质差异不大 /* 确定你的电脑是大端字节序还是小端字节序 */ #include  
     int check2() { 
    union test { 
    char ch; int i; }test0; test0.i = 1; return test0.ch == 0; } int main() { 
    if (check1() == 1) printf("big\n"); else printf("little\n"); return 0; } 
对本例中的联合结构,我们对它求sizeof(test0),会发现它的大小为4,取了int 的大小。 关于union,我们说了,它里边的变量共用一块存储空间,但是它的大小并不总是其中最大的变量所占的空间,还需要考虑对齐! 比如: union test1 { 
    char[5]; int i; } 它的大小就是 8 了! 

2、字节序转换函数

字节序转换函数

 #include  
     //将主机字节序转换为网络字节序 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----longhtons()--"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位的二进制数。   第二步 0 00000000 00000000 00000001 =  (主机字节序)   然后把上面的四部分二进制数从右往左按部分重新排列,那就变为:   第三步 00000001 00000000 00000000 0 =  (网络字节序) 

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 
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.10 address 2: 132.241.5.10 
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/225589.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月17日 上午8:58
下一篇 2026年3月17日 上午8:59


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号