HAOKANG MU /

getaddrinfo默认使用UDP访问DNS SERVER,并依次使用/etc/resolv.conf中的search行的项:

...
socket(PF_INET, SOCK_DGRAM|SOCK_NONBLOCK, IPPROTO_IP) = 4
connect(4, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("172.17.255.10")}, 16) = 0
poll([{fd=4, events=POLLOUT}], 1, 0)    = 1 ([{fd=4, revents=POLLOUT}])
sendto(4, "\332C\1\0\0\1\0\0\0\0\0\0\7nginx-1\5dbyin\3svc\7c"..., 49, MSG_NOSIGNAL, NULL, 0) = 49
poll([{fd=4, events=POLLIN}], 1, 1000)  = 1 ([{fd=4, revents=POLLIN}])
ioctl(4, FIONREAD, [141])               = 0
recvfrom(4, "\332C\201\3\0\1\0\0\0\1\0\0\7nginx-1\5dbyin\3svc\7c"..., 1024, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("172.17.255.10")}, [16]) = 141
close(4)                                = 0
socket(PF_INET, SOCK_DGRAM|SOCK_NONBLOCK, IPPROTO_IP) = 4
connect(4, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("172.17.255.10")}, 16) = 0
poll([{fd=4, events=POLLOUT}], 1, 0)    = 1 ([{fd=4, revents=POLLOUT}])
sendto(4, "\36^\1\0\0\1\0\0\0\0\0\0\7nginx-1\3svc\7cluster"..., 43, MSG_NOSIGNAL, NULL, 0) = 43
poll([{fd=4, events=POLLIN}], 1, 1000)  = 1 ([{fd=4, revents=POLLIN}])
ioctl(4, FIONREAD, [135])               = 0
recvfrom(4, "\36^\201\3\0\1\0\0\0\1\0\0\7nginx-1\3svc\7cluster"..., 1024, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("172.17.255.10")}, [16]) = 135
close(4)                                = 0
socket(PF_INET, SOCK_DGRAM|SOCK_NONBLOCK, IPPROTO_IP) = 4
connect(4, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("172.17.255.10")}, 16) = 0
poll([{fd=4, events=POLLOUT}], 1, 0)    = 1 ([{fd=4, revents=POLLOUT}])
sendto(4, "}\210\1\0\0\1\0\0\0\0\0\0\7nginx-1\7cluster\5loc"..., 39, MSG_NOSIGNAL, NULL, 0) = 39
poll([{fd=4, events=POLLIN}], 1, 1000)  = 1 ([{fd=4, revents=POLLIN}])
ioctl(4, FIONREAD, [131])               = 0
recvfrom(4, "}\210\201\3\0\1\0\0\0\1\0\0\7nginx-1\7cluster\5loc"..., 1024, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("172.17.255.10")}, [16]) = 131
close(4)                                = 0
write(2, "ping: unknown host nginx-1\n", 27ping: unknown host nginx-1
) = 27
exit_group(2)                           = ?

__libc_res_nsearch -> __libc_res_nquerydomain -> __libc_res_nquery -> __libc_res_nsend.

int
__libc_res_nsearch(res_state statp,
		   const char *name,	/* domain name */
		   int class, int type,	/* class and type of query */
		   u_char *answer,	/* buffer to put answer */
		   int anslen,		/* size of answer */
		   u_char **answerp,
		   u_char **answerp2,
		   int *nanswerp2,
		   int *resplen2)
{
///...
	/*
	 * We do at least one level of search if
	 *	- there is no dot and RES_DEFNAME is set, or
	 *	- there is at least one dot, there is no trailing dot,
	 *	  and RES_DNSRCH is set.
	 */
	if ((!dots && (statp->options & RES_DEFNAMES) != 0) || /// ex: hostname
	    (dots && !trailing_dot && (statp->options & RES_DNSRCH) != 0)) {
		int done = 0;

		for (domain = (const char * const *)statp->dnsrch; ///try every entry if failed
		     *domain && !done;
		     domain++) {
			searched = 1;

			if (domain[0][0] == '\0' ||
			    (domain[0][0] == '.' && domain[0][1] == '\0'))
				root_on_list++;

			ret = __libc_res_nquerydomain(statp, name, *domain,
						      class, type,
						      answer, anslen, answerp,
						      answerp2, nanswerp2,
						      resplen2);

在/etc/resolv.conf中配置options:use-vc,让getaddrinfo使用TCP访问Server(glibc 2.14及以上.

int
__libc_res_nsend(res_state statp, const u_char *buf, int buflen,
		 const u_char *buf2, int buflen2,
		 u_char *ans, int anssiz, u_char **ansp, u_char **ansp2,
		 int *nansp2, int *resplen2)
{
//...
		if (__builtin_expect (v_circuit, 0)) { /// use tcp
			/* Use VC; at most one attempt per server. */
			try = statp->retry;
			n = send_vc(statp, buf, buflen, buf2, buflen2,
				    &ans, &anssiz, &terrno,
				    ns, ansp, ansp2, nansp2, resplen2);
			if (n < 0)
				return (-1);
			if (n == 0 && (buf2 == NULL || *resplen2 == 0))
				goto next_ns;
		} else {
			/* Use datagrams. */
			n = send_dg(statp, buf, buflen, buf2, buflen2,
				    &ans, &anssiz, &terrno,
				    ns, &v_circuit, &gotsomewhere, ansp,
				    ansp2, nansp2, resplen2);
			if (n < 0)
				return (-1);
			if (n == 0 && (buf2 == NULL || *resplen2 == 0))
				goto next_ns;
			if (v_circuit)
			  // XXX Check whether both requests failed or
			  // XXX whether one has been answered successfully
				goto same_ns;
		}

参考 getaddrinfo.