1. 概述
在Linux网络编程中,地址转换函数用于在点分十进制字符串和二进制网络字节序之间转换IP地址。这些函数主要定义在 <arpa/inet.h> 头文件中。
2. 主要函数分类
2.1 IPv4专用函数(已过时,但仍有使用)
inet_aton() - 字符串转网络字节序
#include<sys/socket.h>#include<netinet/in.h>#include<arpa/inet.h>intinet_aton(constchar*cp,structin_addr*inp);- 功能:将点分十进制字符串转换为32位网络字节序整数
- 参数:
- cp:点分十进制IP地址字符串(如"192.168.1.1")
- inp:存储转换结果的struct in_addr
- 返回值:成功返回1,失败返回0
inet_addr() - 字符串转网络字节序(有缺陷)
in_addr_tinet_addr(constchar*cp);- 问题:无法处理255.255.255.255(返回INADDR_NONE)
- 不推荐使用,建议使用inet_pton
inet_ntoa() - 网络字节序转字符串
char*inet_ntoa(structin_addrin);- 注意:返回指向静态缓冲区的指针,不可重入
- 线程不安全
关于inet_ntoa
inet_ntoa 这个函数返回了一个char*, 很显然是这个函数自己在内部为我们申请了一块内存来保存ip 的结果. 那么是否需要调用者手动释放呢?
man 手册上说, inet_ntoa 函数, 是把这个返回结果放到了静态存储区. 这个时候不需要我们手动进行释放.
那么问题来了, 如果我们调用多次这个函数, 会有什么样的效果呢? 参见如下代码:
运行结果如下:
因为inet_ntoa 把结果放到自己内部的一个静态存储区, 这样第二次调用时的结果会覆盖掉上一次的结果.
在多线程环境下, 推荐使用inet_ntop, 这个函数由调用者提供一个缓冲区保存结果, 可以规避线程安全问题
2.2 IPv4/IPv6通用函数(推荐)
inet_pton() - 字符串转二进制(可移植)
intinet_pton(intaf,constchar*src,void*dst);- 功能:将字符串地址转换为二进制格式
- 参数:
- af:地址族(AF_INET或AF_INET6)
- src:源字符串
- dst:目标缓冲区
- 返回值:成功返回1,格式无效返回0,错误返回-1
inet_ntop() - 二进制转字符串(可移植)
constchar*inet_ntop(intaf,constvoid*src,char*dst,socklen_t size);- 功能:将二进制地址转换为字符串
- 参数:
- af:地址族
- src:源二进制地址
- dst:目标字符串缓冲区
- size:缓冲区大小(使用INET_ADDRSTRLEN 或INET6_ADDRSTRLEN)
- 返回值:成功返回dst指针,失败返回NULL
3. 缓冲区大小常量
#defineINET_ADDRSTRLEN16// IPv4地址字符串最大长度#defineINET6_ADDRSTRLEN46// IPv6地址字符串最大长度4. 函数对比与选择建议
| 函数 | 地址族 | 线程安全 | 可重入 | 推荐度 |
|---|---|---|---|---|
| inet_aton() | IPv4 | 是 | 是 | ★★★☆☆ |
| inet_addr() | IPv4 | 是 | 是 | ★☆☆☆☆(有缺陷) |
| inet_ntoa() | IPv4 | 否 | 否 | ★☆☆☆☆(线程不安全) |
| inet_pton() | IPv4/IPv6 | 是 | 是 | ★★★★★ |
| inet_ntop() | IPv4/IPv6 | 是 | 是 | ★★★★★ |
总结
- 推荐使用inet_pton()和inet_ntop(),它们支持IPv4/IPv6且线程安全