getaddrinfo根据域名获取IP等信息。
头文件
#include
#include
#include
函数原型
int getaddrinfo(const char *node, const char *service,
const struct addrinfo *hints,
struct addrinfo **res);
void freeaddrinfo(struct addrinfo *res);
const char *gai_strerror(int errcode);
注意在使用getaddrinfo时,const struct addrinfo *hints优先配置SOCK_STREAM域,SOCK_DGRAM有失败的情况。
addrinfo 结构体定义
struct addrinfo {
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
size_t ai_addrlen;
struct sockaddr *ai_addr;
char *ai_canonname;
struct addrinfo *ai_next;
};
示例1:只取第一个IP地址
#include
#include
#include
#include
#include //结构体addrinfo, in_addr
#include
#include
using namespace std;
int main(){
char* hostname = "www.cnblogs.com";//博客园的网址,返回实际IP地址
addrinfo hints, *res;
in_addr addr;
int err;
memset(&hints, 0, sizeof(addrinfo));
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = AF_INET;
if((err = getaddrinfo(hostname, NULL, &hints, &res)) != 0){
printf("error %d : %s\n", err, gai_strerror(err));
return 1;
}
addr.s_addr = ((sockaddr_in*)(res->ai_addr))->sin_addr.s_addr;
printf("ip addresss: %s\n", inet_ntoa(addr));//博客园的网址,返回实际IP地址
freeaddrinfo(res);
return 0;
}
示例2:显示所有域名查找到的所有IP地址
#include
#include
#include
#include
#include
#include
#include
#include //结构体addrinfo, in_addr
#include
#include
using namespace std;
int main(int argc, char **argv){
char *hostname;
struct addrinfo hints,*result, *rp;
int err;
in_addr addr;
//没有输入域名时,博客园的网址,返回实际IP地址
hostname = argc < 2 ? (char *)"www.cnblogs.com" : argv[1];
memset(&hints, 0, sizeof(addrinfo));
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = AF_INET;
if((err = getaddrinfo(hostname, NULL, &hints, &result)) != 0){
printf("error %d : %s\n", err, gai_strerror(err));
return 1;
}
for (rp = result; rp != NULL; rp = rp->ai_next) {
addr.s_addr = ((sockaddr_in*)(rp->ai_addr))->sin_addr.s_addr;
printf("ip addresss: %s\n", inet_ntoa(addr));
}
freeaddrinfo(result);
return 0;
}
一遍都会输出两个IP地址,如www.baidu.com;
示例3:
Server program:
#include
#include
#include
#include
#include
#include
#include
#define BUF_SIZE 500
int main(int argc, char *argv[])
{
struct addrinfo hints;
struct addrinfo *result, *rp;
int sfd, s;
struct sockaddr_storage peer_addr;
socklen_t peer_addr_len;
ssize_t nread;
char buf[BUF_SIZE];
if (argc != 2) {
fprintf(stderr, "Usage: %s port\n", argv[0]);
exit(EXIT_FAILURE);
}
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */
hints.ai_protocol = 0; /* Any protocol */
hints.ai_canonname = NULL;
hints.ai_addr = NULL;
hints.ai_next = NULL;
s = getaddrinfo(NULL, argv[1], &hints, &result);
if (s != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
exit(EXIT_FAILURE);
}
/* getaddrinfo() returns a list of address structures.
Try each address until we successfully bind(2).
If socket(2) (or bind(2)) fails, we (close the socket
and) try the next address. */
for (rp = result; rp != NULL; rp = rp->ai_next) {
sfd = socket(rp->ai_family, rp->ai_socktype,
rp->ai_protocol);
if (sfd == -1)
continue;
if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == 0)
break; /* Success */
close(sfd);
}
if (rp == NULL) { /* No address succeeded */
fprintf(stderr, "Could not bind\n");
exit(EXIT_FAILURE);
}
freeaddrinfo(result); /* No longer needed */
/* Read datagrams and echo them back to sender */
for (;;) {
peer_addr_len = sizeof(struct sockaddr_storage);
nread = recvfrom(sfd, buf, BUF_SIZE, 0,
(struct sockaddr *) &peer_addr, &peer_addr_len);
if (nread == -1)
continue; /* Ignore failed request */
char host[NI_MAXHOST], service[NI_MAXSERV];
s = getnameinfo((struct sockaddr *) &peer_addr,
peer_addr_len, host, NI_MAXHOST,
service, NI_MAXSERV, NI_NUMERICSERV);
if (s == 0)
printf("Received %zd bytes from %s:%s\n",
nread, host, service);
else
fprintf(stderr, "getnameinfo: %s\n", gai_strerror(s));
if (sendto(sfd, buf, nread, 0,
(struct sockaddr *) &peer_addr,
peer_addr_len) != nread)
fprintf(stderr, "Error sending response\n");
}
}
Client program
#include
#include
#include
#include
#include
#include
#include
#define BUF_SIZE 500
int
main(int argc, char *argv[])
{
struct addrinfo hints;
struct addrinfo *result, *rp;
int sfd, s, j;
size_t len;
ssize_t nread;
char buf[BUF_SIZE];
if (argc < 3) {
fprintf(stderr, "Usage: %s host port msg...\n", argv[0]);
exit(EXIT_FAILURE);
}
/* Obtain address(es) matching host/port */
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
hints.ai_flags = 0;
hints.ai_protocol = 0; /* Any protocol */
s = getaddrinfo(argv[1], argv[2], &hints, &result);
if (s != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
exit(EXIT_FAILURE);
}
/* getaddrinfo() returns a list of address structures.
Try each address until we successfully connect(2).
If socket(2) (or connect(2)) fails, we (close the socket
and) try the next address. */
for (rp = result; rp != NULL; rp = rp->ai_next) {
sfd = socket(rp->ai_family, rp->ai_socktype,
rp->ai_protocol);
if (sfd == -1)
continue;
if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1)
break; /* Success */
close(sfd);
}
if (rp == NULL) { /* No address succeeded */
fprintf(stderr, "Could not connect\n");
exit(EXIT_FAILURE);
}
freeaddrinfo(result); /* No longer needed */
/* Send remaining command-line arguments as separate
datagrams, and read responses from server */
for (j = 3; j < argc; j++) {
len = strlen(argv[j]) + 1;
/* +1 for terminating null byte */
if (len > BUF_SIZE) {
fprintf(stderr,
"Ignoring long message in argument %d\n", j);
continue;
}
if (write(sfd, argv[j], len) != len) {
fprintf(stderr, "partial/failed write\n");
exit(EXIT_FAILURE);
}
nread = read(sfd, buf, BUF_SIZE);
if (nread == -1) {
perror("read");
exit(EXIT_FAILURE);
}
printf("Received %zd bytes: %s\n", nread, buf);
}
exit(EXIT_SUCCESS);
}
getaddrinfo函数ipv6的应用
https://blog.csdn.net/u012654882/article/details/51832768
参考资料
https://www.cnblogs.com/xiaoshiwang/p/9763825.html
http://www.man7.org/linux/man-pages/man3/getaddrinfo.3.html
https://blog.csdn.net/fanx021/article/details/80549945
https://blog.csdn.net/u011028408/article/details/84067040
https://blog.csdn.net/jctian000/article/details/81912346