一、预备知识
大端模式、小端模式
- 大端字节序(Big Endian):最高有效位存于最低内存地址处,最低有效位存于最高内存处;
- 小端字节序(Little Endian):最高有效位存于最高内存地址,最低有效位存于最低内存处。
网络字节序
- 我们已经知道,内存中的多字节数据相对于内存地址有大端和小端之分,磁盘文件中的多字节数据相对于文件中的偏移地址也有大端小端之分。网络数据流同样有大端小端之分,也就是说,当接收端收到第一个字节的时候,它将这个字节作为高位字节还是低位字节处理
- 网络数据流的地址应这样规定:先发出的数据是低地址,后发出的数据是高地址
- TCP/IP协议规定:把接收到的第一个字节当作高位字节看待,因此网络数据流应采用大端字节序,即低地址高字节
可以调用以下库函数做网络字节序和主机字节序的转换
#include <arpa/inet.h>
//这些函数调用成功后返回处理后的值,调用失败则返回-1
uint32_t htonl(uint32_t hostlong); //主机字节顺序转换为网络字节顺序 对无符号长型进行操作4bytes
uint16_t htons(uint16_t hostshort); //主机字节顺序转换为网络字节顺序 对无符号短型进行操作2bytes
uint32_t ntohl(uint32_t netlong); //网络字节顺序转换为主机字节顺序 对无符号长型进行操作4bytes
uint16_t ntohs(uint16_t netshort); //网络字节顺序转换为主机字节顺序 对无符号短型进行操作2bytes
IP地址转换函数
- Linux提供了用于将点分十进制表示的IP地址与二进制表示的IP地址相互转换的函数族
早期
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
//数字加点类型 转换成 将32位的IP IP地址存放在参数straddr中,返回结果存放在addrptr中
int inet_aton(const char *straddr, struct in_addr *addrptr);
//将32位的IP 转换成 数字加点类型
char *inet_ntoa(struct in_addr straddr);
//数字加点类型 转换成 将32位的IP
in_addr_t inet_addr(const char *cp);
/*只能处理IPv4的ip地址
不可重入函数
注意参数是struct in_addr*/
现在
#include <arpa/inet.h>
int inet_pton(int af, const char *src, void *dst);
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
/*支持IPv4和IPv6
可重入函数*/
sockaddr数据结构
- Linux中定义了一种通用的套接字结构类型strcut sockaddr,以供不同的协议调用
- strcut sockaddr 很多网络编程函数诞生早于IPv4协议,那时候都使用的是sockaddr结
构体,为了向前兼容,现在sockaddr退化成了(void *)的作用,传递一个地址给函数,至于这个地址类型是sockaddr_in还是sockaddr_in6(文章没有列举出),由地址族确定,然后函数内部再强制类型转化为所需的地址类型
#include <sys/socket.h>