30 sockfd = Socket(AF_INET, SOCK_STREAM, 0);
31 memmove(servaddr.sin_addr, *pptr, sizeof(struct in_addr));
32 printf("trying %s\n",
33 Sock_ntop((SA*)servaddr, sizeof(servaddr)));
34 if (connect(sockfd, (SA*)servaddr, sizeof(servaddr)) == 0)
35 break; /* успех */
36 err_ret("connect error");
37 close(sockfd);
38 }
39 if (*pptr == NULL)
40 err_quit("unable to connect");
41 while ((n = Read(sockfd, recvline, MAXLINE)) 0) {
42 recvline[n] = 0; /* завершающий нуль */
43 Fputs(recvline, stdout);
44 }
45 exit(0);
46 }
11.5. Программа приведена в листинге Д.6.
Листинг Д.6. Модификация листинга 11.2 для работы с IPv4 и IPv6
//names/daytimetcpcli3.c
1 #include "unp.h"
2 int
3 main(int argc, char **argv)
4 {
5 int sockfd, n;
6 char recvline[MAXLINE + 1];
7 struct sockaddr_in servaddr;
8 struct sockaddr_in6 servaddr6;
9 struct sockaddr *sa;
10 socklen_t sal en;
11 struct in_addr **pptr;
12 struct hostent *hp;
13 struct servent *sp;
14 if (argc != 3)
15 err_quit("usage: daytimetcpcli3 hostname service");
16 if ((hp = gethostbyname(argv[1])) == NULL)
17 err_quit("hostname error for %s: %s", argv[1], hstrerror(h_errno));
18 if ((sp = getservbyname(argv[2], "tcp")) == NULL)
19 err_quit("getservbyname error for %s", argv[2]);
20 pptr = (struct in_addr**)hp-h_addr_list;
21 for (; *pptr != NULL; pptr++) {
22 sockfd = Socket(hp-h_addrtype, SOCK_STREAM, 0);
23 if (hp-h_addrtype == AF_INET) {
24 sa = (SA*)servaddr;
25 salen = sizeof(servaddr);
26 } else if (hp-h_addrtype == AF_INET6) {
27 sa = (SA*)servaddr6;
28 salen = sizeof(servaddr6);
29 } else
30 err_quit("unknown addrtype %d", hp-h_addrtype);
31 bzero(sa, salen);
32 sa-sa_family = hp-h_addrtype;
33 sock_set_port(sa, salen, sp-s_port);
34 sock_set_addr(sa, salen, *pptr);
35 printf("trying %s\n", Sock_ntop(sa, salen));
36 if (connect(sockfd, sa, salen) == 0)
37 break; /* успех */
38 err_ret("connect error");
39 close(sockfd);
40 }
41 if (*pptr == NULL)
42 err_quit("unable to connect");
43 while ((n = Read(sockfd, recvline, MAXLINE)) 0) {
44 recvline[n] = 0; /* завершающий нуль */
45 Fputs(recvline, stdout);
46 }
47 exit(0);
48 }
Используем значение
h_addrtype
, возвращаемое функцией
gethostbyname
, для определения типа адреса. Также используем функции
sock_set_port
и
sock_set_addr
(см. раздел 3.8), чтобы установить два соответствующих поля в структуре адреса сокета.