Unix 套接字 - 网络字节顺序

不幸的是,并非所有计算机都以相同的顺序存储组成多字节值的字节。考虑由 2 个字节组成的 16 位互联网。有两种方法可以存储此值。

  • 小端 − 在此方案中,低位字节存储在起始地址 (A) 上,高位字节存储在下一个地址 (A + 1) 上。

  • 大端 −在这个方案中,高位字节存储在起始地址(A)上,低位字节存储在下一个地址(A + 1)上。

为了允许具有不同字节顺序约定的机器相互通信,互联网协议为通过网络传输的数据指定了规范的字节顺序约定。这称为网络字节顺序。

在建立 Internet 套接字连接时,您必须确保 sockaddr_in 结构的 sin_port 和 sin_addr 成员中的数据以网络字节顺序表示。

字节排序函数

在主机内部表示和网络字节顺序之间转换数据的例程如下 −

函数 描述
htons() 主机到网络短
htonl() 主机到网络长
ntohl() 网络到主机长
ntohs() 网络到主机短

下面列出了有关这些函数的更多详细信息 −

  • unsigned short htons(unsigned short hostshort) − 此函数将 16 位(2 字节)数量从主机字节顺序转换为网络字节顺序。

  • unsigned long htonl(unsigned long hostlong) − 此函数将 32 位(4 字节)数量从主机字节顺序转换为网络字节顺序。

  • unsigned short ntohs(unsigned short netshort) − 此函数将 16 位(2 字节)数量从网络字节顺序转换为主机字节顺序。

  • unsigned long ntohl(unsigned long netlong) −此函数将 32 位数量从网络字节顺序转换为主机字节顺序。

这些函数是宏,会导致将转换源代码插入到调用程序中。在小端机器上,代码会将值更改为网络字节顺序。在大端机器上,由于不需要代码,因此不会插入任何代码;函数定义为空。

用于确定主机字节顺序的程序

将以下代码保存在文件 byteorder.c 中,然后对其进行编译并在您的机器上运行。

在此示例中,我们将两字节值 0x0102 存储在短整数中,然后查看两个连续字节 c[0](地址 A)和 c[1](地址 A + 1)以确定字节顺序。

#include <stdio.h>

int main(int argc, char **argv) {

   union {
      short s;
      char c[sizeof(short)];
   }un;
	
   un.s = 0x0102;
   
   if (sizeof(short) == 2) {
      if (un.c[0] == 1 && un.c[1] == 2)
         printf("big-endian
");
      
      else if (un.c[0] == 2 && un.c[1] == 1)
         printf("little-endian
");
      
      else
         printf("unknown
");
   }
   else {
      printf("sizeof(short) = %d
", sizeof(short));
   }
	
   exit(0);
}

该程序在奔腾计算机上生成的输出如下 −

$> gcc byteorder.c
$> ./a.out
little-endian
$>