htonl和ntohl函数
1、什么是字节序
主机字节序: 就是自己的主机内部,内存中数据的处理方式,可以分为两种: 大端字节序(big-endian):按照内存的增长方向,高位数据存储于低位内存中 小端字节序(little-endian):按照内存的增长方向,高位数据存储于低位内存中
网络字节序: 网络字节序转化为主机字节序时,一定要注意是否需要转换。网络字节序是确定的。 网络字节顺序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用big-endian(大端)排序方式。
2、深入理解字节序
网络字节序与主机字节序是经常导致混淆的两个概念,网络字节序是确定的,而主机字节序的多样性往往是混淆的原因。
我们知道数据在传输的过程中,一定有一个标准化的过程,也就是说:从主机a到主机b进行通信应该是这样的, a的固有数据存储-------标准化--------转化成b的固有格式
如上而言:a或者b的固有数据存储格式就是自己的主机字节序,上面的标准化就是网络字节序(也就是大端字节序) a的主机字节序----------网络字节序 ---------b的主机字节序
小结:网络字节序一定是大端,主机字节序不固定
大端字节序(big-endian):按照内存的增长方向,高位数据存储于低位内存中 小端字节序(little-endian):按照内存的增长方向,高位数据存储于低位内存中
数据:0x12345678 从左往右是内存地址增长的方向 低------------------->>>>高 大端字节序:12 34 56 78 小端字节序:78 56 34 12
验证:
#include <stdio.h>
#include <arpa/inet.h>
int main()
{
unsigned long a = 0x12345678;
unsigned char *p = (unsigned char *)(&a);
printf("主机字节序:%0x %0x %0x %0x\n", p[0], p[1], p[2], p[3]);
unsigned long b = htonl(a); //将主机字节序转化成了网络字节序
p = (unsigned char *)(&b);
printf("网络字节序:%0x %0x %0x %0x (大端字节序)\n", p[0], p[1], p[2], p[3]);
return 0;
}
[root@ubuntu0006:~] #./a.out
主机字节序:78 56 34 12
网络字节序:12 34 56 78 (大端字节序)
[root@ubuntu0006:~] #lscpu | grep Byte
Byte Order: Little Endian
3、htonl()函数
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong); "host to network long"
uint16_t htons(uint16_t hostshort); "host to network short"
uint32_t ntohl(uint32_t netlong); "network to host long"
uint16_t ntohs(uint16_t netshort); "network to host short"
将主机数转换成无符号长整型的网络字节顺序。本函数将一个32位数从主机字节顺序转换成网络字节顺序。
h是主机host,n是网络net,l是长整形long,s是短整形short。 一定是无符号的。
3-1、头文件
include
有些系统包含的头文件是
3-2、定义函数
uint32_t htonl(uint32_t hostlong);
hostlong:主机字节顺序表达的32位数。
4、ntohl()函数
将一个无符号长整型数从网络字节顺序转换为主机字节顺序, ntohl()返回一个以主机字节顺序表达的数。
4-1、头文件
linux系统 :#include
4-2、函数形式
uint32_t ntohl(uint32_t netlong); netlong:一个以网络字节顺序表达的32位数。
5、htons() 不常用吧
将主机的无符号短整型数转换成网络字节顺序。hostshort:主机字节顺序表达的16位数。
5-1、头文件
include
5-2、定义函数
u_short PASCAL FAR htons( u_short hostshort); hostshort:主机字节顺序表达的16位数。
5-3、示例
#include <winsock2.h>
#include <iostream>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
int main(){
int a = 16, b;
b = htons(a);
cout << "a=" << a << endl;
cout << "b=" << b << endl;
return 0;
}
运行的结果如下图 a=16 b=4096
解释一下,数字16的16进制表示为0x0010,数字4096的16进制表示为0x1000。 由于Intel机器是小尾端,存储数字16时实际顺序为1000,存储4096时实际顺序为0010。因此在发送网络包时为了报文中数据为0010,需要经过htons进行字节转换。如果用IBM等大尾机器,则没有这种字节顺序转换,但为了程序的可移植性,也最好用这个函数。
6、ntohs()函数
ntohs()是一个函数名,作用是将一个16位数由网络字节顺序转换为主机字节顺序。
6-1、头文件
include
6-2、定义函数
uint16_t ntohs(uint16_t netshort); netshort:一个以网络字节顺序表达的16位数。
linux IP地址转换及网络字节序 文献参考: