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. |