一、主机字节序和网络字节序
-
主机字节序(Host Byte Order):你当前电脑的内存字节顺序(比如 x86 是小端)
-
网络字节序(Network Byte Order):统一规定为大端序(高位字节在高位地址,比较符合人类阅读习惯。)
测试电脑是什么字节序
cpp
void char_testByte()
{
unsigned int i=0x1200;
char *ptr=(char*)&i;
if(*ptr)printf("Big\n");
else printf("Little\n");
}
对于两台使用不同字节序的主机,他们俩之间传输数据时,必然会错误的解释。因此规定大端字节序为网络字节序,以作为共同的一个标准。
Linux提供了如下4个函数来完成主机字节序和网络字节序之间的转换:
cpp
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
//host to network long:把32bit的主机序转换到网络序
uint16_t htons(uint16_t hostshort);
//把16bit的主机序转换到网络序
uint32_t ntohl(uint32_t netlong);
//network to host long:把32bit的网络序转换到主机序
uint16_t ntohs(uint16_t netshort);
//把16bit的网络序转换到主机序
二、socket地址
- UNIX本地域协议族使用下面这个专用socket地址结构体
cpp
struct sockaddr_un {
sa_family_t sun_family; // AF_UNIX
char sun_path[108]; // 套接字路径(如 "/tmp/my_socket")
};
- TCP/IP协议族的专用socket地址结构体如下
- IPv4
cpp
#include <netinet/in.h> // 头文件
struct sockaddr_in {
sa_family_t sin_family; // 地址族(AF_INET)
in_port_t sin_port; // 16位端口号(需用 htons() 转换字节序)
struct in_addr sin_addr; // 32位 IPv4 地址
char sin_zero[8]; // 填充字段(未使用,通常置 0)
};
struct in_addr {
in_addr_t s_addr; // 32位 IPv4 地址(需用 htonl() 转换字节序)
};
- IPv6
cpp
#include <netinet/in.h>
struct sockaddr_in6 {
sa_family_t sin6_family; // 地址族(AF_INET6)
in_port_t sin6_port; // 16位端口号(需用 htons() 转换)
uint32_t sin6_flowinfo; // 流标签(通常为 0)
struct in6_addr sin6_addr; // 128位 IPv6 地址
uint32_t sin6_scope_id; // 接口作用域 ID(用于链路本地地址)
};
struct in6_addr {
unsigned char s6_addr[16]; // 128位 IPv6 地址
};
- IP地址转换函数
-
- 1 所需头文件
cpp
#include<arpa/inet.h>
-
- 2 inet_pton函数:把点分十进制字符串表示的IP地址转成网络字节序表示的IP地址,结果存放在dst所指向的内存。
cpp
int inet_pton(int af,const char * src,void* dst);
官方文档
代码测试
cpp
void test_inet_pton()
{
const char *ip_str = "192.168.0.1";
struct in_addr addr;
int ret = inet_pton(AF_INET, ip_str, &addr);
if (ret == 1) {
printf("[inet_pton] 成功将字符串 \"%s\" 转换为二进制地址\n", ip_str);
printf("[inet_pton] 网络字节序(十六进制): 0x%x\n", ntohl(addr.s_addr));
//先把二进制表示的转换成十六进制形式,也就是网络字节序。(不能直接输出二进制)
} else if (ret == 0) {
printf("[inet_pton] 输入地址无效: %s\n", ip_str);
} else {
perror("[inet_pton] 转换出错");
}
}
-
- 3 inet_ntop函数:把网络字节序表示的IP地址转化成点分十进制表示的IP地址
cpp
const char* inet_ntop(int af,const void* src,char* dst,socklen_t cnt);

代码测试
cpp
void test_inet_ntop()
{
struct in_addr addr;
addr.s_addr = htonl(0xC0A80001); // 十进制 192.168.0.1 的网络字节序
char ip_str[INET_ADDRSTRLEN];
const char *result = inet_ntop(AF_INET, &addr, ip_str, sizeof(ip_str));
if (result != NULL) {
printf("[inet_ntop] 成功将二进制地址转换为字符串: %s\n", ip_str);
} else {
perror("[inet_ntop] 转换出错");
}
}
运行结果