22.5
|
Calling getaddrinfo without a hostname
argument and without the AI_PASSIVE flag set causes it to
assume the local host address: 0::1 (IPv6) and 127.0.0.1 (IPv4).
Recall that an IPv6 socket address structure is returned before an
IPv4 socket address structure by getaddrinfo, assuming
IPv6 is supported. If both protocols are supported on the host, the
call to socket in udp_client will succeed with
the family equal to AF_INET6.
Figure
E.15 is the protocol-independent version of this program.
Figure E.15
Protocol-independent version of program from Section
22.6.
advio/udpserv04.c
1 #include "unpifi.h"
2 void mydg_echo(int, SA *, socklen_t);
3 int
4 main(int argc, char **argv)
5 {
6 int sockfd, family, port;
7 const int on = 1;
8 pid_t pid;
9 socklen_t salen;
10 struct sockaddr *sa, *wild;
11 struct ifi_info *ifi, *ifihead;
12 if (argc == 2)
13 sockfd = Udp_client(NULL, argv[1], (void **) &sa, &salen);
14 else if (argc == 3)
15 sockfd = Udp_client(argv[1], argv[2], (void **) &sa, &salen);
16 else
17 err_quit("usage: udpserv04 [ <host> ] <service or port>");
18 family = sa->sa_family;
19 port = sock_get_port(sa, salen);
20 Close(sockfd); /* we just want family, port, salen */
21 for (ifihead = ifi = Get_ifi_info(family, 1);
22 ifi != NULL; ifi = ifi->ifi_next) {
23 /* bind unicast address */
24 sockfd = Socket(family, SOCK_DGRAM, 0);
25 Setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
26 sock_set_port(ifi->ifi_addr, salen, port);
27 Bind(sockfd, ifi->ifi_addr, salen);
28 printf("bound %s\n", Sock_ntop(ifi->ifi_addr, salen));
29 if ( (pid = Fork()) == 0) { /* child */
30 mydg_echo(sockfd, ifi->ifi_addr, salen);
31 exit(0); /* never executed */
32 }
33 if (ifi->ifi_flags & IFF_BROADCAST) {
34 /* try to bind broadcast address */
35 sockfd = Socket(family, SOCK_DGRAM, 0);
36 Setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
37 sock_set_port(ifi->ifi_brdaddr, salen, port);
38 if (bind(sockfd, ifi->ifi_brdaddr, salen) < 0) {
39 if (errno == EADDRINUSE) {
40 printf("EADDRINUSE: %s\n",
41 Sock_ntop(ifi->ifi_brdaddr, salen));
42 Close(sockfd);
43 continue;
44 } else
45 err_sys("bind error for %s",
46 Sock_ntop(ifi->ifi_brdaddr, salen));
47 }
48 printf("bound %s\n", Sock_ntop(ifi->ifi_brdaddr, salen));
49 if ( (pid = Fork()) == 0) { /* child */
50 mydg_echo(sockfd, ifi->ifi_brdaddr, salen);
51 exit(0); /* never executed */
52 }
53 }
54 }
55 /* bind wildcard address */
56 sockfd = Socket(family, SOCK_DGRAM, 0);
57 Setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
58 wild = Malloc(salen);
59 memcpy(wild, sa, salen); /* copy family and port */
60 sock_set_wild(wild, salen);
61 Bind(sockfd, wild, salen);
62 printf("bound %s\n", Sock_ntop(wild, salen));
63 if ( (pid = Fork()) == 0) { /* child */
64 mydg_echo(sockfd, wild, salen);
65 exit(0); /* never executed */
66 }
67 exit(0);
68 }
69 void
70 mydg_echo(int sockfd, SA *myaddr, socklen_t salen)
71 {
72 int n;
73 char mesg[MAXLINE];
74 socklen_t len;
75 struct sockaddr *cli;
76 cli = Malloc(salen);
77 for ( ; ; ) {
78 len = salen;
79 n = Recvfrom(sockfd, mesg, MAXLINE, 0, cli, &len);
80 printf("child %d, datagram from %s", getpid(), Sock_ntop(cli, len));
81 printf(", to %s\n", Sock_ntop(myaddr, salen));
82 Sendto(sockfd, mesg, n, 0, cli, len);
83 }
84 }
|