Code Example:
The following programs demonstrate the use of getaddrinfo(), gai_strerror(), freeaddrinfo(), and getnameinfo(). The programs are an echo server and client for UDP datagrams.
伺服器端程式:
1 ###Server program 2 3 #include <sys/types.h> 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <unistd.h> 7 #include <string.h> 8 #include <sys/socket.h> 9 #include <netdb.h> 10 11 #define BUF_SIZE 500 12 13 int 14 main(int argc, char *argv[]) 15 { 16 struct addrinfo hints; 17 struct addrinfo *result, *rp; 18 int sfd, s; 19 struct sockaddr_storage peer_addr; 20 socklen_t peer_addr_len; 21 ssize_t nread; 22 char buf[BUF_SIZE]; 23 24 if (argc != 2) { 25 fprintf(stderr, "Usage: %s port ", argv[0]); 26 exit(EXIT_FAILURE); 27 } 28 29 memset(&hints, 0, sizeof(struct addrinfo)); 30 hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ 31 hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ 32 hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */ 33 hints.ai_protocol = 0; /* Any protocol */ 34 hints.ai_canonname = NULL; 35 hints.ai_addr = NULL; 36 hints.ai_next = NULL; 37 38 s = getaddrinfo(NULL, argv[1], &hints, &result); 39 if (s != 0) { 40 fprintf(stderr, "getaddrinfo: %s ", gai_strerror(s)); 41 exit(EXIT_FAILURE); 42 } 43 44 /* getaddrinfo() returns a list of address structures. 45 Try each address until we successfully bind(2). 46 If socket(2) (or bind(2)) fails, we (close the socket 47 and) try the next address. */ 48 49 for (rp = result; rp != NULL; rp = rp->ai_next) { 50 sfd = socket(rp->ai_family, rp->ai_socktype, 51 rp->ai_protocol); 52 if (sfd == -1) 53 continue; 54 55 if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == 0) 56 break; /* Success */ 57 58 close(sfd); 59 } 60 61 if (rp == NULL) { /* No address succeeded */ 62 fprintf(stderr, "Could not bind "); 63 exit(EXIT_FAILURE); 64 } 65 66 freeaddrinfo(result); /* No longer needed */ 67 68 /* Read datagrams and echo them back to sender */ 69 70 for (;;) { 71 peer_addr_len = sizeof(struct sockaddr_storage); 72 nread = recvfrom(sfd, buf, BUF_SIZE, 0, 73 (struct sockaddr *) &peer_addr, &peer_addr_len); 74 if (nread == -1) 75 continue; /* Ignore failed request */ 76 77 char host[NI_MAXHOST], service[NI_MAXSERV]; 78 79 s = getnameinfo((struct sockaddr *) &peer_addr, 80 peer_addr_len, host, NI_MAXHOST, 81 service, NI_MAXSERV, NI_NUMERICSERV); 82 if (s == 0) 83 printf("Received %zd bytes from %s:%s ", 84 nread, host, service); 85 else 86 fprintf(stderr, "getnameinfo: %s ", gai_strerror(s)); 87 88 if (sendto(sfd, buf, nread, 0, 89 (struct sockaddr *) &peer_addr, 90 peer_addr_len) != nread) 91 fprintf(stderr, "Error sending response "); 92 } 93 }
客戶端程式:
1 ###Client program 2 3 #include <sys/types.h> 4 #include <sys/socket.h> 5 #include <netdb.h> 6 #include <stdio.h> 7 #include <stdlib.h> 8 #include <unistd.h> 9 #include <string.h> 10 11 #define BUF_SIZE 500 12 13 int 14 main(int argc, char *argv[]) 15 { 16 struct addrinfo hints; 17 struct addrinfo *result, *rp; 18 int sfd, s, j; 19 size_t len; 20 ssize_t nread; 21 char buf[BUF_SIZE]; 22 23 if (argc < 3) { 24 fprintf(stderr, "Usage: %s host port msg... ", argv[0]); 25 exit(EXIT_FAILURE); 26 } 27 28 /* Obtain address(es) matching host/port */ 29 30 memset(&hints, 0, sizeof(struct addrinfo)); 31 hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ 32 hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ 33 hints.ai_flags = 0; 34 hints.ai_protocol = 0; /* Any protocol */ 35 36 s = getaddrinfo(argv[1], argv[2], &hints, &result); 37 if (s != 0) { 38 fprintf(stderr, "getaddrinfo: %s ", gai_strerror(s)); 39 exit(EXIT_FAILURE); 40 } 41 42 /* getaddrinfo() returns a list of address structures. 43 Try each address until we successfully connect(2). 44 If socket(2) (or connect(2)) fails, we (close the socket 45 and) try the next address. */ 46 47 for (rp = result; rp != NULL; rp = rp->ai_next) { 48 sfd = socket(rp->ai_family, rp->ai_socktype, 49 rp->ai_protocol); 50 if (sfd == -1) 51 continue; 52 53 if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1) 54 break; /* Success */ 55 56 close(sfd); 57 } 58 59 if (rp == NULL) { /* No address succeeded */ 60 fprintf(stderr, "Could not connect "); 61 exit(EXIT_FAILURE); 62 } 63 64 freeaddrinfo(result); /* No longer needed */ 65 66 /* Send remaining command-line arguments as separate 67 datagrams, and read responses from server */ 68 69 for (j = 3; j < argc; j++) { 70 len = strlen(argv[j]) + 1; 71 /* +1 for terminating null byte */ 72 73 if (len + 1 > BUF_SIZE) { 74 fprintf(stderr, 75 "Ignoring long message in argument %d ", j); 76 continue; 77 } 78 79 if (write(sfd, argv[j], len) != len) { 80 fprintf(stderr, "partial/failed write "); 81 exit(EXIT_FAILURE); 82 } 83 84 nread = read(sfd, buf, BUF_SIZE); 85 if (nread == -1) { 86 perror("read"); 87 exit(EXIT_FAILURE); 88 } 89 90 printf("Received %zd bytes: %s ", nread, buf); 91 } 92 93 exit(EXIT_SUCCESS); 94 }
Come from url: http://man7.org/linux/man-pages/man3/getaddrinfo.3.html