Beej's Simple Client example code iterates over all IP addresses returned from getaddrinfo(), until it can connect to the first one. See the code below.
Is this always necessary, or is it OK to assume that we only have to try to connect to the first address returned by getaddrinfo()?
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if ((rv = getaddrinfo(argv[1], PORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// ------------------------------------------------------------
// loop through all the results and connect to the first we can
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("client: socket");
continue;
}
if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("client: connect");
continue;
}
break;
}
The getaddrinfo() function translates the name of a service location (for example, a host name) and/or service name and returns a set of socket addresses and associated information to be used in creating a socket with which to address the specified service.
“getaddrinfo,” as the name indicates, is used to get the address information. getaddrinfo() is used to convert a text string that is human readable and represents the hostnames or IP address into a link that is dynamically allocated to the linked list of addrinfo structures.
The sorting function used within getaddrinfo() is defined in RFC 3484; the order can be tweaked for a particular system by editing /etc/gai. conf (available since glibc 2.5).
ptr->ai_family is just an integer, a member of a struct addrinfo. ( And if you are wondering about the particular syntax of ptr-> , you can go through this question ), it will have a value of either AF_INET or AF_INET6 (Or in theory any other supported protocol)
Yes, you should iterate over all the addresses - in particular, consider the case when the destination host has IPv6 addresses enabled but your local host does not. getaddrinfo()
will return AF_INET6
family addresses, but then either the socket()
or connect()
call will fail.
It's also a possibility that your host supports multiple protocols implementing SOCK_STREAM
(say, SCTP in addition to TCP) and the destination host does not - since you haven't set the ai_protocol
member of the hints structure, addresses representing all protocols supporting SOCK_STREAM
sockets will be returned.
In addition to the other answers given above, consider the common case that for larger websites and so on, that multiple A records might be published, for redundancy purposes. If a connect()
to the first address fails, you want to try the others as well.
Let look at tit this way... The server host you want to connect to may have several addresses associated with it, but the actual server program only listens on one of those addresses. If your client doesn't know the exact address the server program is listening to, you have to try all the addresses the host has until you find the correct one and can connect.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With