一般数据在内存中是按照字节存储的,存储的方式分为大端和小端。在不知道对方主机的存储方式的情况下,我们不知道是否需要转换数据的存储方式。因此,TCP/IP协议规定:发送到网络的数据流应采用大端字节序!
如果当前主机是大端,那就可以忽略直接发送;否则就需要转化成大端再发送,下面提供了一些网络字节序和主机字节序的转换函数。
目录
1、端口号的网络字节序转换
(1) 本地字节序 => 网络字节序
(2) 网络字节序 => 本地字节序
2、本地IP 与 网络字节序IP 的相互转换
1、端口号的网络字节序转换
h 代表 host,n 表示 network
(1) 本地字节序 => 网络字节序
服务端和客户端通信时要交换地址和端口,即端口和ip地址会被送入网络,port作为主机上的变量,是主机序列,需要转化为网络字节序。
htonl:host to network,由32位本地字节序转换成网络字节序。
htons:host to network,由16位本地字节序转换成网络字节序。
注意:以htonl为例,如果主机是小端序,那么该函数就会将数据字节序转化为大端;如果主机是大端序,该函数不会做任何操作。下面由网络字节序到本地字节序的转换也是同理。
(2) 网络字节序 => 本地字节序
在获取对端的端口号时,端口号因为是随网络报文一起发送过来的,此时端口号是网络字节序,要获取到正确的端口号,需要将端口号转换成本地字节序。
ntohl:network to host,当网络字节序为32位整型时,由网络字节序转化为主机字节序。
ntohs:network to host,当网络字节序为16位整型时,由网络字节序转化为主机字节序。
2、本地IP 与 网络字节序IP 的相互转换
站在客户端的角度,在网络通信的时候,一般IP地址和端口号要发送给对端,而我们使用的IP地址是点分十进制的,比如127.0.0.1,这样传递起来不是特别方便,我们需要先将其转化为四字节的整数,然后再转化为网络字节序。
站在服务端的角度,如果你想要拿到对端的IP地址,那就需要将网络字节序转化为本地主机字节序,然后再转化为点分十进制的字符串IP。
Linux给我们提供了这两者的转换函数
inet_addr 函数只要提供对应的字符串
inet_addr("127.0.0.1"); //将点分十进制的字符串IP地址转化为网络字节序的形式
inet_ntoa 函数要提供保存地址信息的结构体,结构体的声明如下:
struct in_addr in;
in.s_addr = addr; // 假设addr是网络字节序的IP地址
const char* client_ip = inet_ntoa(in);