| Previous | Next
Interprocess Communication with Pipes and SocketsContents:Handling Unsolicited Media Changes
The term interprocess communication describes a scenario in which two or more processes talk to one another. The processes may reside on the same computer or they may be on separate computers connected via a network. In Unix, there are several IPC mechanisms: pipes, semaphores, signals, shared memory, and sockets, to name a few. All are useful for local communication, but sockets are typically used for communication over a network. The problem with reading and writing a network socket is that an I/O operation often takes a considerable amount of time to complete, which, as described in "Anatomy of the MainLoop", might block the flow of Tk events. Your program then stalls, and the user becomes unhappy. But with care, it's possible to mix network developing with Perl/Tk and still maintain lively event processing. Now, we'll write some Perl/Tk network programs using pipes and sockets. In "IPC with send", we'll cover more examples using an IPC mechanism unique to Tk, the send command. The first example in this chapter is a simple TCP/IP media change client/server, just to become familiar with the basic mechanisms. These programs help automate daily tape backups on a Linux computer. The client sends an operator message to a central machine, requesting a tape change, and the server posts the message in a Perl/Tk window and returns the operator's response. Later, we'll develop a Tk user interface that updates flat files on a remote machine, but won't freeze in the face of I/O delays and timeouts due to network latency or disabled servers. The model is extremely simple; it depends on
Handling Unsolicited Media ChangesA good system administrator always implements backup procedures, which protect her machines from damaged disks, malevolent miscreants, or rash But our administrator, in accordance with Perl's First Virtue, Laziness, is also likely to initiate these backups via cron or some similar automated means, which means there is no terminal for the backup program to communicate with her. Fortunately, the backup program has an option to run a user-specified program when a media change is required. This alert program is typically a script to send a mail message or display a window that attracts the operator's attention. Sending mail seems to lack style. But opening a window is cool unless there are many machines, each with its own window, so let's write a TCP/IP server that displays media change messages in Tk windows on a single machine, as they arrive from any number of backup client machines. The Media Change Client, mediachangecWhen the system backup reaches end of volume, it executes this incredibly simple client code, specifying the IP address of the media change server plus a message string to display. The code first opens a socket to the server and unbuffers it.[49]
The
As shown in Figure 19-1, the response comes directly from a messageBox widget posted on the server's display and can be either "Ok" or "Cancel." Figure 19-1. A media change operator messageThe Media Change Server, mediachangedWe're about to see a forking TCP/IP server, sometimes called a network daemon. In typical Unix fashion, we'll call it mediachanged, with the trailing d identifying it as a daemon program. This bare-bones example serves as the basis for the much more complicated IPADM server discussed in the remaining sections of this chapter. The following code is initiated on the media change server at boot time and runs forever. It opens a listen socket on the little-known port 8979 and, as requests arrive, it forks a new child that creates a Tk MainWindow with a lone messageBox widget. Here are the preamble statements: #!/usr/local/bin/perl -w # # mediachanged - media change daemon. # # Wait for connect on our well known port, display the received message # in a Tk messageBox, and return the operator's reply. use 5.005; use IO::Handle; use IO::Socket; use Net::hostent; use POSIX qw/setsid/; use Tk; use subs qw/client_connect/; use strict; This statement ensures that the daemon's children are properly disposed of after they terminate:
The program backgrounds itself by forking and terminating the parent: my $pid = fork; die "fork failed: $!" unless defined $pid; exit if $pid; # parent exits, daemon continues setsid or die "setsid failed: $!"; Here we create a listen socket, distinct from the client's connect socket, differentiated by the my $server = IO::Socket::INET->new( Proto => 'tcp', LocalPort => 8979, Listen => SOMAXCONN, Reuse => 1, ); die "Socket::INET::new failed: $!" unless defined $server; At last, here is the daemon's main loop, where it blocks on the The daemon then quickly spawns a child to handle the request and resumes waiting on the
Subroutine
Armed with the know-how to build a TCP/IP client/server, let's examine a more complicated scenario involving a Perl/Tk client. |