有两组地址转换函数,他们在ASCII字符串(这是人们偏爱使用的格式,比如用点分十进制字符串表示IPv4地址,十六进制表示IPv6地址)与网络字节序的二进制值(这是存放在套接字地址结构中的值)之间转换网际地址。
(1)下面3个函数用于点分十进制字符串表示的IPv4地址及用网络字节序整数表示的IPv4地址之间的转换。
#include <arpa/inet.h>
in_addr_t inet_addr(const char* strptr);//返回:若字符串有效则为32位二进制网络字节序的IPV4地址,否则为INADDR_NONE
int inet_aton(const char* cp, struct in_addr* inp);//返回:若字符串有效则为1,否则为0
char* inet_ntoa(struct in_addr in);//返回:指向一个点分十进制数串的指针
inet_addr函数将用点分十进制字符串表示的IPv4地址转化为用网络字节序整数表示的IPv4地址。
失败时返回INADDR_NONE。但该函数存在一个问题:
- 所有个可能的二进制值都是有效的IP地址(从0.0.0.0到255.255.255.255),但是当出错时该函数返回INADDR_NONE常值(通常是一个32位均为1的值)。这意味着点分十进制数串255.255.255.255(这是IPv4的有限广播地址)不能由该函数处理,因为它的二进制值被用来指示该函数失败。
- 另一个潜在的问题是,一些手册页面声明该函数出错时返回-1而不是INADDR_NONE。这样对该函数的返回值(一个无符号的值)和一个负常数值(-1)进行比较时可能会发生问题,具体取决于C编译器。
inet_aton函数完成和inet_addr同样的功能,但是将转化结果存储于参数inp指向的地址结构中。
成功返回1,失败返回0。
inet_ntoa函数将用网络字节序整数表示的IPv4地址转化为用点分十进制字符串表示的IPv4地址。
该函数内部用一个静态变量存储转化的结果,函数返回值指向该静态内存,因此inet_ntoa是不可重入的。
不可重入的inet_ntoa函数,例子:
char* szValue1 = inet_ntoa("1.2.3.4");
char* szValue2 = inet_ntoa("5.6.7.8");
printf("address 1: %s\n", szValue1);
printf("address 2: %s\n", szValue2);
运行结果:
address1: 5.6.7.8
address2: 5.6.7.8
(2)随IPv6出现的新函数。下面两个新的函数也可完成前面三个函数的功能,对于IPv4和IPv6地址都适用。
#include <arpa/inet.h>
int inet_pton(int af, const char* src, void* dst);//返回:若成功则为1,若输入不是有效的表达格式则为0,若出错则为-1
const char* inet_ntop(int af, const void* src, char* dst, socklen_t cnt);//返回:若成功则为之乡结果的指针,若出错则为NULL
inet_pton函数将用字符串表示的IP地址src(点分十进制IPv4或十六进制IPv6字符串)转换成网络字节序整数表示的IP地址,并把转换结果存储于dst指向的内存中。
参数af:指定地址族,AF_INET或者AF_INET6。
返回值:
成功返回1,失败返回0并设置errno。
inet_ntop函数进行相反的转换,前三个参数的含义与inet_pton的参数相同,最后一个参数cnt指定目标存储单元的大小,以免该函数溢出其调用者的缓冲区。为了有助于指定这个大小,<netinet/in.h>头文件中定义了如下两个宏:
#include <netinet/in.h>
#define INET_ADDRSTRLEN 16
#define INET6_ADDRSTRLEN 46
net_ntop成功时返回目标存储单元的地址,失败返回NULL并设置errno。