getaddrinfo的作用就是按照提示填充指定的数据结构,以供bind connect 等函数直接使用,无需手动填充所需数据结构 例如 sockaddr,这个函数的作用是替换以前的gethostbyname
例子:
/* ** showipandprot.c */ #include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <arpa/inet.h> #include <netinet/in.h> int main(int argc, char *argv[]) { struct addrinfo hints, *res, *p; int status; char ipstr[INET6_ADDRSTRLEN]; uint16_t port; if (argc < 2) { fprintf(stderr,"usage: %s hostname port\n",argv[0]); return 1; } memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; // AF_INET 或 AF_INET6 hints.ai_socktype = SOCK_STREAM; if ((status = getaddrinfo(argv[1], argv[2], &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; if (p->ai_family == AF_INET) { // IPv4 struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr; addr = &(ipv4->sin_addr); ipver = "IPv4"; port =ntohs(((struct sockaddr_in*)p->ai_addr)->sin_port); } else { // IPv6 struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr; addr = &(ipv6->sin6_addr); ipver = "IPv6"; port =ntohs(((struct sockaddr_in6*)p->ai_addr)->sin6_port); } // convert the IP to a string and print it: inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr); printf(" %s: %s,port is %u\n", ipver, ipstr,port); } freeaddrinfo(res); return 0; }
ps:客户端程序也可以使用bind 使用某一个interface于服务器通信,如果指定了端口则使用指定端口进行通信,如果不指定端口则随机使用一个未被使用的端口
服务端也一样 如果没指定端口 则随机绑定监听一个端口
reference:
http://www.cnblogs.com/skynet/archive/2010/12/12/1903949.html#!comments
http://www.cnblogs.com/cxz2009/archive/2010/11/19/1881693.html
http://www.linuxhowtos.org/C_C++/socket.htm
http://beej-zhtw.netdpi.net/05-system-call-or-bust/5-1-getaddrinfo-start 本文的例子是在该文章里面的代码基础上修改的