[ Team LiB ] |
15.6 Unix Domain Datagram Client/ServerWe now recode our UDP client/server from Sections 8.3 and 8.5 to use Unix domain datagram sockets. Figure 15.5 shows the server, which is a modification of Figure 8.3. Figure 15.4 Unix domain stream protocol echo client.unixdomain/unixstrcli01.c 1 #include "unp.h" 2 int 3 main(int argc, char **argv) 4 { 5 int sockfd; 6 struct sockaddr_un servaddr; 7 sockfd = Socket(AF_LOCAL, SOCK_STREAM, 0); 8 bzero(&servaddr, sizeof(servaddr)); 9 servaddr.sun_family = AF_LOCAL; 10 strcpy(servaddr.sun_path, UNIXSTR_PATH); 11 Connect(sockfd, (SA *) &servaddr, sizeof(servaddr)); 12 str_cli(stdin, sockfd); /* do it all */ 13 exit(0); 14 } Figure 15.5 Unix domain datagram protocol echo server.unixdomain/unixdgserv01.c 1 #include "unp.h" 2 int 3 main(int argc, char **argv) 4 { 5 int sockfd; 6 struct sockaddr_un servaddr, cliaddr; 7 sockfd = Socket(AF_LOCAL, SOCK_DGRAM, 0); 8 unlink(UNIXDG_PATH); 9 bzero(&servaddr, sizeof(servaddr)); 10 servaddr.sun_family = AF_LOCAL; 11 strcpy(servaddr.sun_path, UNIXDG_PATH); 12 Bind(sockfd, (SA *) &servaddr, sizeof(servaddr)); 13 dg_echo(sockfd, (SA *) &cliaddr, sizeof(cliaddr)); 14 } 6 The datatype of the two socket address structures is now sockaddr_un. 7 The first argument to socket is AF_LOCAL, to create a Unix domain datagram socket. 8–12 The constant UNIXDG_PATH is defined in unp.h to be /tmp/unix.dg. We first unlink the pathname, in case it exists from an earlier run of the server, and then initialize the socket address structure before calling bind. An error from unlink is acceptable. 13 The same dg_echo function is used (Figure 8.4). Figure 15.6 is the Unix domain datagram protocol echo client. It is a modification of Figure 8.7. Figure 15.6 Unix domain datagram protocol echo client.unixdomain/unixdgcli01.c 1 #include "unp.h" 2 int 3 main(int argc, char **argv) 4 { 5 int sockfd; 6 struct sockaddr_un cliaddr, servaddr; 7 sockfd = Socket(AF_LOCAL, SOCK_DGRAM, 0); 8 bzero(&cliaddr, sizeof(cliaddr)); /* bind an address for us */ 9 cliaddr.sun_family = AF_LOCAL; 10 strcpy(cliaddr.sun_path, tmpnam(NULL)); 11 Bind(sockfd, (SA *) &cliaddr, sizeof(cliaddr)); 12 bzero(&servaddr, sizeof(servaddr)); /* fill in server's address */ 13 servaddr.sun_family = AF_LOCAL; 14 strcpy(servaddr.sun_path, UNIXDG_PATH); 15 dg_cli(stdin, sockfd, (SA *) &servaddr, sizeof(servaddr)); 16 exit(0); 17 } 6 The socket address structure to contain the server's address is now a sockaddr_un structure. We also allocate one of these structures to contain the client's address, which we will talk about shortly. 7 The first argument to socket is AF_LOCAL. 8–11 Unlike our UDP client, when using the Unix domain datagram protocol, we must explicitly bind a pathname to our socket so that the server has a pathname to which it can send its reply. We call tmpnam to assign a unique pathname that we then bind to our socket. Recall from Section 15.4 that sending a datagram on an unbound Unix domain datagram socket does not implicitly bind a pathname to the socket. Therefore, if we omit this step, the server's call to recvfrom in the dg_echo function returns a null pathname, which then causes an error when the server calls sendto. 12–14 The code to fill in the socket address structure with the server's well-known pathname is identical to the code shown earlier for the server. 15 The function dg_cli is the same as that shown in Figure 8.8. |
[ Team LiB ] |