网络编程--网络字节序和主机字节序详解

NBO : 网络字节序
HBO : 主机字节序
LE little-endian:小端
BE big-endian:大端

空中传输的字节的顺序即网络字节序为标准顺序,考虑到与协议的一致以及与同类其它平台产品的互通,在程序中发数据包时,将主机字节序转换为网络字节序,收数据包处将网络字 节序转换为主机字节序。网络程序开发时 或是跨平台开发时 应该注意保证只用一种字节序 不然两方的解释不一样就会产生bug。

数据在传输的过程中,一定有一个标准化的过程,也就是说:从主机a到主机b进行通信:a的主机字节序----------网络字节序 ---------b的主机字节序

一、主机字节序:

自己的主机内部,内存中数据的处理方式,可以分为两种:
大端字节序:按照内存的增长方向,高位数据存储于低位内存中(最直观的字节序 )
小端字节序:按照内存的增长方向,高位数据存储于高位内存中(符合人的思维的字节序)

二、网络字节序:

网络数据流也有大小端之分。
网络数据流的地址规定:先发出的数据是低地址,后发出的数据是高地址。
发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出,为了不使数据流乱序,接收主机也会把从网络上接收的数据按内存地址从低到高的顺序保存在接收缓冲区中。
TCP/IP协议规定:网络数据流应采用大端字节序,即低地址高字节。

三、常用的转换函数:

linux的头文件 : #include

htons() : 由主机字节序转换为网络字节序的16位整数值。(host to net)
ntohs() : 由网络字节序转换为主机字节序的16位整数值。
htonl () : 由主机字节序转换为网络字节序的32位整数值。
ntohl () : 由网络字节序转换为主机字节序的32位整数值。

如何判断我们的主机是那一种的呢???这个我们可以通过程序来进行验证:
方法一:

  1 #include
  2 #include
  3 
  4 int main()
  5 {
  6         union
  7         {
  8                 short s;
  9                 char c[sizeof(short)];
 10         }un;
 11         un.s = 0x0102;
 12         if(sizeof(short)==2)
 13         {
 14                 if(un.c[0] == 1 && un.c[1] == 2)
 15                         printf("Big-Endian\n");
 16                 else if(un.c[0] == 2 && un.c[1] == 1)
 17                         printf("Little-Endian\n");
 18                 else
 19                         printf("Unknown\n");
 20         }
 21         else
 22                 print("sizeof(short)=%d\n",sizeof(short));
 23         exit(0);
 24 }

编译 && 运行 ----- Linux(LE):

$ uname -a
Linux localhost.localdomain 2.6.32-642.el6.x86_64 #1 SMP Tue May 10 17:27:01 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
$ gcc -o byte-order byte-order.c
$ ./byte-order 
Little-Endian

方法二:

#include 
#include 
#include 
#include 

int main()
{
    uint16_t HostByteOrder = 0x0102;
    uint16_t NetByteOrder = htons(HostByteOrder);
    if (HostByteOrder == NetByteOrder)
        printf("Big Endian\n");
    else
        printf("Little Endian\n");
    return 0;
}

原理是:
我虽然不知道主机字节序是啥,但是我可以通过htons这样的函数,将其统一转换为网络字节序。
网络字节序是大端(BE)。我拿转换前的数值和转换后的大端数值进行比较:
如果相等,说明当前主机字节序等价于网络字节序,BE;否则,当前主机字节序为LE。

需要注意:
构建主机字节序的数值时,不要使在LE和BE下都一样的数值,例如:
(16BIT):
0XFFFFFFFF
0XAABBBBAA
这样的数值,在LE和BE下数值都是相等的,=.=!!!

你可能感兴趣的:(socket通信,网络序,主机序,高位,低位,htons,ntohs,htonl,ntohl)