第二类为同时支持IPv4和IPv6。包括,inet_pton和inet_ntop。其定义如下:
#include <netinet/in.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。
#define INET_ADDRSTRLEN 16
#define INET6_ADDRSTRLEN 46
其中各参数的含义如下:
af参数指定地址族。可选为:AF_INET和AF_INET6;
src为转换源,dst为转换目标。这里要注意的是,不能传给inet_ntop一个空指针,必须是一个已分配目标大小内存的指针。
cnt参数指定目标存储单位的大小。上面定义的两个宏可以帮助指定IPv4和IPv6的特定大小。
用法如下:
#include <arpa/inet.h>
#include <stdio.h>
int main(){
char* ip = “1.2.3.4”;
struct in_addr addr;
int i = 0;
int *ad = &i;
inet_pton(AF_INET, ip, ad);
printf("%d
", *ad);
char ip2[INET_ADDRSTRLEN];
char* ip3 = inet_ntop(AF_INET, ad, ip2, INET_ADDRSTRLEN);
printf("%s
“, ip2);
printf(”%s
", ip3);
return 0;
}
struct sockaddr {
unsigned short sa_family; /* address family, AF_xxx /
char sa_data[14]; / 14 bytes of protocol address */
};
struct sockaddr_in {
short int sin_family; /* Address family AF_INET /
unsigned short int sin_port; / Port number /
struct in_addr sin_addr; / Internet address /
unsigned char sin_zero[8]; / Same size as struct sockaddr /
};
struct in_addr {
unsigned long s_addr; / Internet address */
};
struct sockaddr_in6 {
sa_family_t sin6_family; /* AF_INET6 /
in_port_t sin6_port; / transport layer port # /
uint32_t sin6_flowinfo; / IPv6 traffic class & flow info /
struct in6_addr sin6_addr; / IPv6 address /
uint32_t sin6_scope_id; / set of interfaces for a scope /
};
struct in6_addr {
uint8_t s6_addr[16]; / IPv6 address */
};
struct addrinfo{
int ai_flags; /* AI_PASSIVE,AI_CANONNAME,AI_NUMERICHOST /
int ai_family; / AF_INET,AF_INET6 /
int ai_socktype; / SOCK_STREAM,SOCK_DGRAM /
int ai_protocol; / IPPROTO_IP, IPPROTO_IPV4, IPPROTO_IPV6 /
size_t ai_addrlen; / Length */
char ai_cannoname; / */
struct sockaddr ai_addr; / struct sockaddr */
struct addrinfo ai_next; / pNext */
}
函数原型:
int inet_pton(int af, const char *src, void *dst);
//这个函数转换字符串到网络地址,第一个参数af是地址族,转换后存在dst中 af的值可为AF_INET (代表使用IPv4协议)或AF_INET6(代表作用IPv6协议)
const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt);
//这个函数转换网络二进制结构到ASCII类型的地址,参数的作用和上面相同,只是多了一个参数socklen_t cnt,
//他是所指向缓存区dst的大小,避免溢出,如果缓存区太小无法存储地址的值,则返回一个空指针,并将errno置为ENOSPC
举例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
int main(int argc, char **argv)
{
unsigned char buf[sizeof(struct in6_addr)];
int domain, s;
char str[INET6_ADDRSTRLEN];
if(argc != 3){
fprintf(stderr, "usage: %s {i4|i6|<num>} string/n", argv[0]);
exit(EXIT_FAILURE);
}
domain = (strcmp(argv[1], "i4") == 0) ? AF_INET:(strcmp(argv[1], "i6") == 0) ? AF_INET6 : atoi(argv[1]);
//IP字符串 ——》网络字节流
s = inet_pton(domain, argv[2], buf);
if(s<=0){
if(0 == s)
fprintf(stderr, "Not in presentation format/n");
else
perror("inet_pton");
exit(EXIT_FAILURE);
}
//网络字节流 ——》IP字符串
if(inet_ntop(domain, buf, str, INET6_ADDRSTRLEN) == NULL){
perror("inet ntop/n");
exit(EXIT_FAILURE);
}
printf("%s/n", str);
exit(EXIT_SUCCESS);
}