Using UNIX-Domain Sockets for Datagrams


 
Network Programming with Perl
By Lincoln  D.  Stein
Slots : 1
Table of Contents
Chapter  22.   UNIX-Domain Sockets

    Content

A "Wrap" Server

As a sample application we'll use the standard Text::Wrap module to create a simple text-formatting server. The server accepts a chunk of text input, reformats it into narrow 30-column paragraphs, and returns the reformatted text to the client. The server, named wrap_serv.pl uses the standard forking architecture and the IO::Socket::UNIX library. The client, wrap_cli.pl , uses a simple design that sends the entire input file to the server, shuts down the socket for writing, and then reads back the reformatted data. The following is an example of the output from the client after feeding it an excerpt from the beginning of this chapter:

 %  wrap_cli.pl ../ch22.txt  Connected to /tmp/wrapserv... 

In previous chapters we have focused on TCP/IP sockets, which were designed to allow processes on different hosts to communicate. Sometimes, however, you'd like two or more processes on the same host to exchange messages. Although TCP/IP sockets can be used for this purpose (and often are), an alternative is to use UNIX-domain sockets, which were designed to support local communications.

The advantage of UNIX-domain sockets over TCP/IP for local interprocess communication...

The Text::Wrap Server

Figure 22.1 lists wrap_serv.pl . It uses the forking design familiar from previous chapters. For simplicity, the server doesn't autobackground itself, write a PID file, or add any of the other frills discussed earlier, but this would be simple to add with the Daemon module developed in Chapter 14.

Figure 22.1. wrap_serv.pl , the text-formatting server

graphics/22fig01.gif

Lines 1 “4: Import modules We load the IO::Socket module and import the fill() subroutine from Text::Wrap. Since this is a forking server, we import the WNOHANG constant from POSIX for use in the CHLD handler. We also bring in the POSIX :signal_h set to block and unblock signals. This facility will be used in the call to fork() .

Lines 5 “8: Define constants We define a SOCK_PATH constant containing the UNIX-domain socket path and various format settings to be passed to Text::Wrap.

Lines 9 “12: Set up variables We retrieve the socket path from the command line or default to the one in SOCK_PATH . We set the Text::Wrap $ columns variable to the column width defined in COLUMNS .

Lines 13 “16: Install signal handlers The CHLD signal reaps all child processes using a variant of the waitpid() loop that we saw earlier. This server must also unlink the UNIX-domain socket file before it terminates, and for this reason we intercept the INT and TERM signals with a handler that unlinks the file and then terminates normally.

Lines 17 “18: Set umask We explicitly set the umask to octal 0111 so that the listening socket will be created world readable and writable. This allows any process on the local host to communicate with the server. (The leading is crucial for making 0111 interpreted as an octal constant. If omitted, Perl interprets this as decimal 111 , which is something else entirely.)

Lines 19 “21: Create listening socket We call IO::Socket::UNIX->new() to create a UNIX-domain listening socket on the selected socket address path. The Listen argument is set to the SOMAXCONN constant exported by the Socket and IO::Socket modules.

Lines 22 “32: accept() loop The accept() loop is identical to similar loops used in TCP/IP servers. We do, however, call fork() through a launch_child() wrapper for reasons that we will discuss next . The interact() function is responsible for communication with the client and is run in the child process.

Lines 33 “42: launch_child() subroutine launch_child() is a wrapper around fork() . Because the parent server process has INT and TERM handlers that unlink the socket file, we must be careful to remove these handlers from the children; otherwise , the file might be unlinked prematurely. Using the same strategy we developed in the Daemon module of Chapter 14, we create a POSIX:: SigSet containing the INT , CHLD , and TERM signals and invoke sigprocmask () to block the signals temporarily. With the signals now safely blocked, we fork() , and reset each of the handlers to the default behavior in the child. We now unblock signals by calling sigprocmask() again and return the child's PID.

Lines 43 “48: interact() subroutine The routine that does all the real work is only six lines long. It retrieves the connected socket from its argument list, reads the list of text lines to format from the socket, and calls chomp() to remove the newlines, if any. It then passes the lines to the Text::Wrap fill() function, sends the result across the socket, and closes the socket.

The Text::Wrap Client

Figure 22.2 lists wrap_cli.pl , which is a mere 12 lines long.

Figure 22.2. wrap_cli.pl , the text-formatting client

graphics/22fig02.gif

Lines 1 “3: Import modules We bring in the IO::Socket and Getopt::Long modules. The latter is used for processing command-line switches.

Line 4: Define SOCK_PATH constant We define a constant containing the default path to the UNIX-domain socket.

Lines 5 “7: Process command-line arguments The client allows the user to manually set the path to the socket by providing a $path argument. We call GetOptions() to parse the command-line looking for this argument. If not provided, we default to the value of SOCK_PATH .

Lines 8 “9: Open socket We call the one-argument form of IO::Socket::UNIX->new() to create a new UNIX-domain socket and attempt to connect to the address at $path . We don't need to set our umask before calling new() , because we will not be binding to a local address.

Lines 10 “12: Read text lines and send them to server We use <> to read all the lines from STDIN and/or the command-line argument list into an array named @lines , and send them over the socket to the server. We then invoke shutdown(1) to close the write-half of the socket and indicate to the server that we have no more data to submit.

Line 13: Print the results We read the reformatted lines from the socket and print them to STDOUT .


   
Top


Network Programming with Perl
Network Programming with Perl
ISBN: 0201615711
EAN: 2147483647
Year: 2000
Pages: 173

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net