结构struct:
struct addrinfo {
int ai_flags; // AI_PASSIVE, AI_CANONNAME, etc.
int ai_family; // AF_INET, AF_INET6, AF_UNSPEC通信类型
int ai_socktype; // SOCK_STREAM, SOCK_DGRAM
int ai_protocol; // use 0 for "any"
size_t ai_addrlen; // size of ai_addr in bytes
struct sockaddr *ai_addr; // struct sockaddr_in or _in6 存储地址和端口的指针<见下面的结构定义>
char *ai_canonname; // full canonical hostname
struct addrinfo *ai_next; // linked list, next node 返回的结构链表指针
};
下面的sockaddr 存储地址信息,这里一眼还看不到任何的有用的信息
struct sockaddr {
unsigned short sa_family; // address family, AF_xxx
char sa_data[14]; // 14 bytes of protocol address
};但是从下面的结构就可一看到具体的地址等有效信息,有用的信息是:struct sockaddr指针和 struct sockaddr_in指针可以相互转换,着就方便了读取地址中的各部分信息。
// (IPv4 only--see struct sockaddr_in6 for IPv6)
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 32bit表示,并非我们通常说的点分模式
unsigned char sin_zero[8]; // Same size as struct sockaddr
};
其中struct in_addr如下定义
// Internet address (a structure for historical reasons)
struct in_addr {
uint32_t s_addr; // that's a 32-bit int (4 bytes)
};对于ipv6的结构可以参考如下
struct sockaddr_in6 {
u_int16_t sin6_family; // address family, AF_INET6
u_int16_t sin6_port; // port number, Network Byte Order
u_int32_t sin6_flowinfo; // IPv6 flow information
struct in6_addr sin6_addr; // IPv6 address
u_int32_t sin6_scope_id; // Scope ID
};
struct in6_addr {
unsigned char s6_addr[16]; // IPv6 address
};
/———————————————————————————————————结构至此—————————————————————————————————————————————/
地址的转换问题,由点分到in_addr(也就时位模式)
struct sockaddr_in in4;
struct sockaddr_in6 in6;
inet_pton(AF_INET, "192.0.2.1", &(sa.sin_addr)); // IPv4
inet_pton(AF_INET6, "2001:db8:63b3:1::3490", &(sa6.sin6_addr)); // IPv6
参数:0:网络类型(AF_INET or AF_INET6)1:点分模式(ipv6冒号隔开)3:转换的地址后存储位置指针
由位模式转换为点分模式(char *模式)eg.
char ipv4[INET_ADDRSTRLEN]; //足够的长度存储
char ipv6[INET6_ADDRSTRLEN];//
inet_ntop(AF_INET, &(sa.sin_addr), ipv4, sizeof ipv4);
inet_ntop(AF_INET6, &(sa.sin6_addr), ipv6, sizeof ipv6);
参数:0:网络类型(AF_INET or AF_INET6)1:为模式的指针 3:转换的地址后存储位置指针,4存储大小。
下面看getaddrinfo函数,次函数兼容ipv6
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
int getaddrinfo(const char *node, // e.g. "www.example.com" or IP
const char *service, // e.g. "http" or port number
const struct addrinfo *hints,
struct addrinfo **res);参数:0:host or IP
1:service Linux 下可以通过gedit /etc/services 查看
2:hints 是一个你预先配的结构,填充你想要相关信息的信息
3:res 起始就是一个指向返回的 Linked List 的指针
由于返回的List时动态的所有在最后要释放这些结构链表,通过一个结构就可以做到:
freeaddrinfo(res);
一个例子:
/*
** showip.c -- show IP addresses for a host given on the command line
*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
struct addrinfo hints, *res, *p;
int status;
char ipstr[INET6_ADDRSTRLEN];
if (argc != 2) {
fprintf(stderr,"usage: showip hostname\n");
return 1;
}
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // AF_INET or AF_INET6 to force version
hints.ai_socktype = SOCK_STREAM;
if ((status = getaddrinfo(argv[1], NULL, &hints, &res)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
return 2;
}
printf("IP addresses for %s:\n\n", argv[1]);
for(p = res;p != NULL; p = p->ai_next) {
void *addr;
char *ipver;
// get the pointer to the address itself,
// different fields in IPv4 and IPv6:
if (p->ai_family == AF_INET) { // IPv4
struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
addr = &(ipv4->sin_addr);
ipver = "IPv4";
} else { // IPv6
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
addr = &(ipv6->sin6_addr);
ipver = "IPv6";
}
// convert the IP to a string and print it:
inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr);
printf(" %s: %s\n", ipver, ipstr);
}
freeaddrinfo(res); // free the linked list
return 0;
}
run:
showip www.baidu.com
The IP address for www.baidu.com is
IPV4: 119.75.218.70
IPV4: 119.75.217.109
本文参考了http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html
其他资料:http://blog.youkuaiyun.com/xjtuse_mal/article/details/1967471http://blog.youkuaiyun.com/xjtuse_mal/article/details/1967471
man手册:man getaddrinfo