11.14 udp_client
Function
Our functions that provide a simpler interface
to getaddrinfo change with UDP because we provide one
client function that creates an unconnected UDP socket, and another
in the next section that creates a connected UDP socket.
#include "unp.h"
|
int udp_client (const char
*hostname, const char
*service, struct sockaddr
**saptr, socklen_t
*lenp);
|
Returns: unconnected socket descriptor if OK, no
return on error
|
This function creates an unconnected UDP socket,
returning three items. First, the return value is the socket
descriptor. Second, saptr is the
address of a pointer (declared by the caller) to a socket address
structure (allocated dynamically by udp_client), and in
that structure, the function stores the destination IP address and
port for future calls to sendto. The size of the socket
address structure is returned in the variable pointed to by
lenp. This final argument cannot
be a null pointer (as we allowed for the final argument to
tcp_listen) because the length of the socket address
structure is required in any calls to sendto and
recvfrom.
Figure
11.15 shows the source code for this function.
Figure 11.15
udp_client function: creates an unconnected UDP
socket.
lib/udp_client.c
1 #include "unp.h"
2 int
3 udp_client (const char *host, const char *serv, SA **saptr, socklen_t *lenp)
4 {
5 int sockfd, n;
6 struct addrinfo hints, *res, *ressave;
7 bzero(&hints, sizeof (struct addrinfo));
8 hints.ai_family = AF_UNSPEC;
9 hints.ai_socktype = SOCK_DGRAM;
10 if ( (n = getaddrinfo (host, serv, &hints, &res)) ! = 0)
11 err_quit ("udp_client error for %s, %s: %s",
12 host, serv, gai_strerror(n));
13 ressave = res;
14 do {
15 sockfd = socket (res->ai_family, res->ai_socktype, res->ai_protocol);
16 if (sockfd >= 0)
17 break; /* success */
18 } while ( (res = res->ai_next) ! = NULL);
19 if (res == NULL) /* errno set from final socket () */
20 err_sys ("udp_client error for %s, %s", host, serv);
21 *saptr = Malloc (res->ai_addrlen);
22 memcpy (*saptr, res->ai_addr, res->ai_addrlen);
23 *lenp = res->ai_addrlen;
24 freeaddrinfo (ressave);
25 return (sockfd);
26 }
getaddrinfo converts the hostname and service arguments. A datagram socket is
created. Memory is allocated for one socket address structure, and
the socket address structure corresponding to the socket that was
created is copied into the memory.
Example: Protocol-Independent Daytime
Client
We now recode our daytime client from Figure
11.11 to use UDP and our udp_client function.
Figure 11.16 shows the
protocol-independent source code.
Figure 11.16
UDP daytime client using our udp_client function.
names/daytimeudpcli1.c
1 #include "unp.h"
2 int
3 main(int argc, char **argv)
4 {
5 int sockfd, n;
6 char recvline [MAXLINE + 1];
7 socklen_t salen;
8 struct sockaddr *sa;
9 if (argc ! = 3)
10 err_quit
11 ("usage: daytimeudpclil <hostname/IPaddress> <service/port#>");
12 sockfd = Udp_client (argv [1], argv [2], (void **) &sa, &salen);
13 printf ("sending to %s\n", Sock_ntop_host (sa, salen));
14 Sendto (sockfd, "", 1, 0, sa, salen); /* send 1-byte datagram */
15 n = Recvfrom (sockfd, recvline, MAXLINE, 0 NULL, NULL);
16 recvline [n] = '\0'; /* null terminate */
17 Fputs (recvline, stdout);
18 exit (0);
19 }
12鈥?7
We call our udp_client function and then print the IP
address and port of the server to which we will send the UDP
datagram. We send a one-byte datagram and then read and print the
reply.
We need to send only a zero-byte UDP datagram,
as what triggers the daytime server's response is just the arrival
of a datagram, regardless of its length and contents. But, many
SVR4 implementations do not allow a zero-length UDP datagram.
We run our client specifying a hostname that has
a AAAA record and an A record. Since the structure with the AAAA
record is returned first by getaddrinfo, an IPv6 socket is
created.
freebsd % daytimeudpcli1 aix daytime
sending to 3ffe:b80:1f8d:2:204:acff:fe17:bf38
Sun Jul 27 23:21:12 2003
Next, we specify the dotted-decimal address of
the same host, resulting in an IPv4 socket.
freebsd % daytimeudpclil 192.168.42.2 daytime
sending to 192.168.42.2
Sun Jul 27 23:21:40 2003
|