1N/A=head1 NAME
1N/A
1N/Aperlipc - Perl interprocess communication (signals, fifos, pipes, safe subprocesses, sockets, and semaphores)
1N/A
1N/A=head1 DESCRIPTION
1N/A
1N/AThe basic IPC facilities of Perl are built out of the good old Unix
1N/Asignals, named pipes, pipe opens, the Berkeley socket routines, and SysV
1N/AIPC calls. Each is used in slightly different situations.
1N/A
1N/A=head1 Signals
1N/A
1N/APerl uses a simple signal handling model: the %SIG hash contains names
1N/Aor references of user-installed signal handlers. These handlers will
1N/Abe called with an argument which is the name of the signal that
1N/Atriggered it. A signal may be generated intentionally from a
1N/Aparticular keyboard sequence like control-C or control-Z, sent to you
1N/Afrom another process, or triggered automatically by the kernel when
1N/Aspecial events transpire, like a child process exiting, your process
1N/Arunning out of stack space, or hitting file size limit.
1N/A
1N/AFor example, to trap an interrupt signal, set up a handler like this:
1N/A
1N/A sub catch_zap {
1N/A my $signame = shift;
1N/A $shucks++;
1N/A die "Somebody sent me a SIG$signame";
1N/A }
1N/A $SIG{INT} = 'catch_zap'; # could fail in modules
1N/A $SIG{INT} = \&catch_zap; # best strategy
1N/A
1N/APrior to Perl 5.7.3 it was necessary to do as little as you possibly
1N/Acould in your handler; notice how all we do is set a global variable
1N/Aand then raise an exception. That's because on most systems,
1N/Alibraries are not re-entrant; particularly, memory allocation and I/O
1N/Aroutines are not. That meant that doing nearly I<anything> in your
1N/Ahandler could in theory trigger a memory fault and subsequent core
1N/Adump - see L</Deferred Signals (Safe Signals)> below.
1N/A
1N/AThe names of the signals are the ones listed out by C<kill -l> on your
1N/Asystem, or you can retrieve them from the Config module. Set up an
1N/A@signame list indexed by number to get the name and a %signo table
1N/Aindexed by name to get the number:
1N/A
1N/A use Config;
1N/A defined $Config{sig_name} || die "No sigs?";
1N/A foreach $name (split(' ', $Config{sig_name})) {
1N/A $signo{$name} = $i;
1N/A $signame[$i] = $name;
1N/A $i++;
1N/A }
1N/A
1N/ASo to check whether signal 17 and SIGALRM were the same, do just this:
1N/A
1N/A print "signal #17 = $signame[17]\n";
1N/A if ($signo{ALRM}) {
1N/A print "SIGALRM is $signo{ALRM}\n";
1N/A }
1N/A
1N/AYou may also choose to assign the strings C<'IGNORE'> or C<'DEFAULT'> as
1N/Athe handler, in which case Perl will try to discard the signal or do the
1N/Adefault thing.
1N/A
1N/AOn most Unix platforms, the C<CHLD> (sometimes also known as C<CLD>) signal
1N/Ahas special behavior with respect to a value of C<'IGNORE'>.
1N/ASetting C<$SIG{CHLD}> to C<'IGNORE'> on such a platform has the effect of
1N/Anot creating zombie processes when the parent process fails to C<wait()>
1N/Aon its child processes (i.e. child processes are automatically reaped).
1N/ACalling C<wait()> with C<$SIG{CHLD}> set to C<'IGNORE'> usually returns
1N/AC<-1> on such platforms.
1N/A
1N/ASome signals can be neither trapped nor ignored, such as
1N/Athe KILL and STOP (but not the TSTP) signals. One strategy for
1N/Atemporarily ignoring signals is to use a local() statement, which will be
1N/Aautomatically restored once your block is exited. (Remember that local()
1N/Avalues are "inherited" by functions called from within that block.)
1N/A
1N/A sub precious {
1N/A local $SIG{INT} = 'IGNORE';
1N/A &more_functions;
1N/A }
1N/A sub more_functions {
1N/A # interrupts still ignored, for now...
1N/A }
1N/A
1N/ASending a signal to a negative process ID means that you send the signal
1N/Ato the entire Unix process-group. This code sends a hang-up signal to all
1N/Aprocesses in the current process group (and sets $SIG{HUP} to IGNORE so
1N/Ait doesn't kill itself):
1N/A
1N/A {
1N/A local $SIG{HUP} = 'IGNORE';
1N/A kill HUP => -$$;
1N/A # snazzy writing of: kill('HUP', -$$)
1N/A }
1N/A
1N/AAnother interesting signal to send is signal number zero. This doesn't
1N/Aactually affect a child process, but instead checks whether it's alive
1N/Aor has changed its UID.
1N/A
1N/A unless (kill 0 => $kid_pid) {
1N/A warn "something wicked happened to $kid_pid";
1N/A }
1N/A
1N/AWhen directed at a process whose UID is not identical to that
1N/Aof the sending process, signal number zero may fail because
1N/Ayou lack permission to send the signal, even though the process is alive.
1N/AYou may be able to determine the cause of failure using C<%!>.
1N/A
1N/A unless (kill 0 => $pid or $!{EPERM}) {
1N/A warn "$pid looks dead";
1N/A }
1N/A
1N/AYou might also want to employ anonymous functions for simple signal
1N/Ahandlers:
1N/A
1N/A $SIG{INT} = sub { die "\nOutta here!\n" };
1N/A
1N/ABut that will be problematic for the more complicated handlers that need
1N/Ato reinstall themselves. Because Perl's signal mechanism is currently
1N/Abased on the signal(3) function from the C library, you may sometimes be so
1N/Amisfortunate as to run on systems where that function is "broken", that
1N/Ais, it behaves in the old unreliable SysV way rather than the newer, more
1N/Areasonable BSD and POSIX fashion. So you'll see defensive people writing
1N/Asignal handlers like this:
1N/A
1N/A sub REAPER {
1N/A $waitedpid = wait;
1N/A # loathe sysV: it makes us not only reinstate
1N/A # the handler, but place it after the wait
1N/A $SIG{CHLD} = \&REAPER;
1N/A }
1N/A $SIG{CHLD} = \&REAPER;
1N/A # now do something that forks...
1N/A
1N/Aor better still:
1N/A
1N/A use POSIX ":sys_wait_h";
1N/A sub REAPER {
1N/A my $child;
1N/A # If a second child dies while in the signal handler caused by the
1N/A # first death, we won't get another signal. So must loop here else
1N/A # we will leave the unreaped child as a zombie. And the next time
1N/A # two children die we get another zombie. And so on.
1N/A while (($child = waitpid(-1,WNOHANG)) > 0) {
1N/A $Kid_Status{$child} = $?;
1N/A }
1N/A $SIG{CHLD} = \&REAPER; # still loathe sysV
1N/A }
1N/A $SIG{CHLD} = \&REAPER;
1N/A # do something that forks...
1N/A
1N/ASignal handling is also used for timeouts in Unix, While safely
1N/Aprotected within an C<eval{}> block, you set a signal handler to trap
1N/Aalarm signals and then schedule to have one delivered to you in some
1N/Anumber of seconds. Then try your blocking operation, clearing the alarm
1N/Awhen it's done but not before you've exited your C<eval{}> block. If it
1N/Agoes off, you'll use die() to jump out of the block, much as you might
1N/Ausing longjmp() or throw() in other languages.
1N/A
1N/AHere's an example:
1N/A
1N/A eval {
1N/A local $SIG{ALRM} = sub { die "alarm clock restart" };
1N/A alarm 10;
1N/A flock(FH, 2); # blocking write lock
1N/A alarm 0;
1N/A };
1N/A if ($@ and $@ !~ /alarm clock restart/) { die }
1N/A
1N/AIf the operation being timed out is system() or qx(), this technique
1N/Ais liable to generate zombies. If this matters to you, you'll
1N/Aneed to do your own fork() and exec(), and kill the errant child process.
1N/A
1N/AFor more complex signal handling, you might see the standard POSIX
1N/Amodule. Lamentably, this is almost entirely undocumented, but
1N/Athe F<t/lib/posix.t> file from the Perl source distribution has some
1N/Aexamples in it.
1N/A
1N/A=head2 Handling the SIGHUP Signal in Daemons
1N/A
1N/AA process that usually starts when the system boots and shuts down
1N/Awhen the system is shut down is called a daemon (Disk And Execution
1N/AMONitor). If a daemon process has a configuration file which is
1N/Amodified after the process has been started, there should be a way to
1N/Atell that process to re-read its configuration file, without stopping
1N/Athe process. Many daemons provide this mechanism using the C<SIGHUP>
1N/Asignal handler. When you want to tell the daemon to re-read the file
1N/Ayou simply send it the C<SIGHUP> signal.
1N/A
1N/ANot all platforms automatically reinstall their (native) signal
1N/Ahandlers after a signal delivery. This means that the handler works
1N/Aonly the first time the signal is sent. The solution to this problem
1N/Ais to use C<POSIX> signal handlers if available, their behaviour
1N/Ais well-defined.
1N/A
1N/AThe following example implements a simple daemon, which restarts
1N/Aitself every time the C<SIGHUP> signal is received. The actual code is
1N/Alocated in the subroutine C<code()>, which simply prints some debug
1N/Ainfo to show that it works and should be replaced with the real code.
1N/A
1N/A #!/usr/bin/perl -w
1N/A
1N/A use POSIX ();
1N/A use FindBin ();
1N/A use File::Basename ();
1N/A use File::Spec::Functions;
1N/A
1N/A $|=1;
1N/A
1N/A # make the daemon cross-platform, so exec always calls the script
1N/A # itself with the right path, no matter how the script was invoked.
1N/A my $script = File::Basename::basename($0);
1N/A my $SELF = catfile $FindBin::Bin, $script;
1N/A
1N/A # POSIX unmasks the sigprocmask properly
1N/A my $sigset = POSIX::SigSet->new();
1N/A my $action = POSIX::SigAction->new('sigHUP_handler',
1N/A $sigset,
1N/A &POSIX::SA_NODEFER);
1N/A POSIX::sigaction(&POSIX::SIGHUP, $action);
1N/A
1N/A sub sigHUP_handler {
1N/A print "got SIGHUP\n";
1N/A exec($SELF, @ARGV) or die "Couldn't restart: $!\n";
1N/A }
1N/A
1N/A code();
1N/A
1N/A sub code {
1N/A print "PID: $$\n";
1N/A print "ARGV: @ARGV\n";
1N/A my $c = 0;
1N/A while (++$c) {
1N/A sleep 2;
1N/A print "$c\n";
1N/A }
1N/A }
1N/A __END__
1N/A
1N/A
1N/A=head1 Named Pipes
1N/A
1N/AA named pipe (often referred to as a FIFO) is an old Unix IPC
1N/Amechanism for processes communicating on the same machine. It works
1N/Ajust like a regular, connected anonymous pipes, except that the
1N/Aprocesses rendezvous using a filename and don't have to be related.
1N/A
1N/ATo create a named pipe, use the Unix command mknod(1) or on some
1N/Asystems, mkfifo(1). These may not be in your normal path.
1N/A
1N/A # system return val is backwards, so && not ||
1N/A #
1N/A $ENV{PATH} .= ":/etc:/usr/etc";
1N/A if ( system('mknod', $path, 'p')
1N/A && system('mkfifo', $path) )
1N/A {
1N/A die "mk{nod,fifo} $path failed";
1N/A }
1N/A
1N/A
1N/AA fifo is convenient when you want to connect a process to an unrelated
1N/Aone. When you open a fifo, the program will block until there's something
1N/Aon the other end.
1N/A
1N/AFor example, let's say you'd like to have your F<.signature> file be a
1N/Anamed pipe that has a Perl program on the other end. Now every time any
1N/Aprogram (like a mailer, news reader, finger program, etc.) tries to read
1N/Afrom that file, the reading program will block and your program will
1N/Asupply the new signature. We'll use the pipe-checking file test B<-p>
1N/Ato find out whether anyone (or anything) has accidentally removed our fifo.
1N/A
1N/A chdir; # go home
1N/A $FIFO = '.signature';
1N/A $ENV{PATH} .= ":/etc:/usr/games";
1N/A
1N/A while (1) {
1N/A unless (-p $FIFO) {
1N/A unlink $FIFO;
1N/A system('mknod', $FIFO, 'p')
1N/A && die "can't mknod $FIFO: $!";
1N/A }
1N/A
1N/A # next line blocks until there's a reader
1N/A open (FIFO, "> $FIFO") || die "can't write $FIFO: $!";
1N/A print FIFO "John Smith (smith\@host.org)\n", `fortune -s`;
1N/A close FIFO;
1N/A sleep 2; # to avoid dup signals
1N/A }
1N/A
1N/A=head2 Deferred Signals (Safe Signals)
1N/A
1N/AIn Perls before Perl 5.7.3 by installing Perl code to deal with
1N/Asignals, you were exposing yourself to danger from two things. First,
1N/Afew system library functions are re-entrant. If the signal interrupts
1N/Awhile Perl is executing one function (like malloc(3) or printf(3)),
1N/Aand your signal handler then calls the same function again, you could
1N/Aget unpredictable behavior--often, a core dump. Second, Perl isn't
1N/Aitself re-entrant at the lowest levels. If the signal interrupts Perl
1N/Awhile Perl is changing its own internal data structures, similarly
1N/Aunpredictable behaviour may result.
1N/A
1N/AThere were two things you could do, knowing this: be paranoid or be
1N/Apragmatic. The paranoid approach was to do as little as possible in your
1N/Asignal handler. Set an existing integer variable that already has a
1N/Avalue, and return. This doesn't help you if you're in a slow system call,
1N/Awhich will just restart. That means you have to C<die> to longjump(3) out
1N/Aof the handler. Even this is a little cavalier for the true paranoiac,
1N/Awho avoids C<die> in a handler because the system I<is> out to get you.
1N/AThe pragmatic approach was to say ``I know the risks, but prefer the
1N/Aconvenience'', and to do anything you wanted in your signal handler,
1N/Aand be prepared to clean up core dumps now and again.
1N/A
1N/AIn Perl 5.7.3 and later to avoid these problems signals are
1N/A"deferred"-- that is when the signal is delivered to the process by
1N/Athe system (to the C code that implements Perl) a flag is set, and the
1N/Ahandler returns immediately. Then at strategic "safe" points in the
1N/APerl interpreter (e.g. when it is about to execute a new opcode) the
1N/Aflags are checked and the Perl level handler from %SIG is
1N/Aexecuted. The "deferred" scheme allows much more flexibility in the
1N/Acoding of signal handler as we know Perl interpreter is in a safe
1N/Astate, and that we are not in a system library function when the
1N/Ahandler is called. However the implementation does differ from
1N/Aprevious Perls in the following ways:
1N/A
1N/A=over 4
1N/A
1N/A=item Long running opcodes
1N/A
1N/AAs Perl interpreter only looks at the signal flags when it about to
1N/Aexecute a new opcode if a signal arrives during a long running opcode
1N/A(e.g. a regular expression operation on a very large string) then
1N/Asignal will not be seen until operation completes.
1N/A
1N/A=item Interrupting IO
1N/A
1N/AWhen a signal is delivered (e.g. INT control-C) the operating system
1N/Abreaks into IO operations like C<read> (used to implement Perls
1N/AE<lt>E<gt> operator). On older Perls the handler was called
1N/Aimmediately (and as C<read> is not "unsafe" this worked well). With
1N/Athe "deferred" scheme the handler is not called immediately, and if
1N/APerl is using system's C<stdio> library that library may re-start the
1N/AC<read> without returning to Perl and giving it a chance to call the
1N/A%SIG handler. If this happens on your system the solution is to use
1N/AC<:perlio> layer to do IO - at least on those handles which you want
1N/Ato be able to break into with signals. (The C<:perlio> layer checks
1N/Athe signal flags and calls %SIG handlers before resuming IO operation.)
1N/A
1N/ANote that the default in Perl 5.7.3 and later is to automatically use
1N/Athe C<:perlio> layer.
1N/A
1N/ANote that some networking library functions like gethostbyname() are
1N/Aknown to have their own implementations of timeouts which may conflict
1N/Awith your timeouts. If you are having problems with such functions,
1N/Ayou can try using the POSIX sigaction() function, which bypasses the
1N/APerl safe signals (note that this means subjecting yourself to
1N/Apossible memory corruption, as described above). Instead of setting
1N/AC<$SIG{ALRM}> try something like the following:
1N/A
1N/A use POSIX;
1N/A sigaction SIGALRM, new POSIX::SigAction sub { die "alarm\n" }
1N/A or die "Error setting SIGALRM handler: $!\n";
1N/A
1N/A=item Restartable system calls
1N/A
1N/AOn systems that supported it, older versions of Perl used the
1N/ASA_RESTART flag when installing %SIG handlers. This meant that
1N/Arestartable system calls would continue rather than returning when
1N/Aa signal arrived. In order to deliver deferred signals promptly,
1N/APerl 5.7.3 and later do I<not> use SA_RESTART. Consequently,
1N/Arestartable system calls can fail (with $! set to C<EINTR>) in places
1N/Awhere they previously would have succeeded.
1N/A
1N/ANote that the default C<:perlio> layer will retry C<read>, C<write>
1N/Aand C<close> as described above and that interrupted C<wait> and
1N/AC<waitpid> calls will always be retried.
1N/A
1N/A=item Signals as "faults"
1N/A
1N/ACertain signals e.g. SEGV, ILL, BUS are generated as a result of
1N/Avirtual memory or other "faults". These are normally fatal and there
1N/Ais little a Perl-level handler can do with them. (In particular the
1N/Aold signal scheme was particularly unsafe in such cases.) However if
1N/Aa %SIG handler is set the new scheme simply sets a flag and returns as
1N/Adescribed above. This may cause the operating system to try the
1N/Aoffending machine instruction again and - as nothing has changed - it
1N/Awill generate the signal again. The result of this is a rather odd
1N/A"loop". In future Perl's signal mechanism may be changed to avoid this
1N/A- perhaps by simply disallowing %SIG handlers on signals of that
1N/Atype. Until then the work-round is not to set a %SIG handler on those
1N/Asignals. (Which signals they are is operating system dependant.)
1N/A
1N/A=item Signals triggered by operating system state
1N/A
1N/AOn some operating systems certain signal handlers are supposed to "do
1N/Asomething" before returning. One example can be CHLD or CLD which
1N/Aindicates a child process has completed. On some operating systems the
1N/Asignal handler is expected to C<wait> for the completed child
1N/Aprocess. On such systems the deferred signal scheme will not work for
1N/Athose signals (it does not do the C<wait>). Again the failure will
1N/Alook like a loop as the operating system will re-issue the signal as
1N/Athere are un-waited-for completed child processes.
1N/A
1N/A=back
1N/A
1N/AIf you want the old signal behaviour back regardless of possible
1N/Amemory corruption, set the environment variable C<PERL_SIGNALS> to
1N/AC<"unsafe"> (a new feature since Perl 5.8.1).
1N/A
1N/A=head1 Using open() for IPC
1N/A
1N/APerl's basic open() statement can also be used for unidirectional
1N/Ainterprocess communication by either appending or prepending a pipe
1N/Asymbol to the second argument to open(). Here's how to start
1N/Asomething up in a child process you intend to write to:
1N/A
1N/A open(SPOOLER, "| cat -v | lpr -h 2>/dev/null")
1N/A || die "can't fork: $!";
1N/A local $SIG{PIPE} = sub { die "spooler pipe broke" };
1N/A print SPOOLER "stuff\n";
1N/A close SPOOLER || die "bad spool: $! $?";
1N/A
1N/AAnd here's how to start up a child process you intend to read from:
1N/A
1N/A open(STATUS, "netstat -an 2>&1 |")
1N/A || die "can't fork: $!";
1N/A while (<STATUS>) {
1N/A next if /^(tcp|udp)/;
1N/A print;
1N/A }
1N/A close STATUS || die "bad netstat: $! $?";
1N/A
1N/AIf one can be sure that a particular program is a Perl script that is
1N/Aexpecting filenames in @ARGV, the clever programmer can write something
1N/Alike this:
1N/A
1N/A % program f1 "cmd1|" - f2 "cmd2|" f3 < tmpfile
1N/A
1N/Aand irrespective of which shell it's called from, the Perl program will
1N/Aread from the file F<f1>, the process F<cmd1>, standard input (F<tmpfile>
1N/Ain this case), the F<f2> file, the F<cmd2> command, and finally the F<f3>
1N/Afile. Pretty nifty, eh?
1N/A
1N/AYou might notice that you could use backticks for much the
1N/Asame effect as opening a pipe for reading:
1N/A
1N/A print grep { !/^(tcp|udp)/ } `netstat -an 2>&1`;
1N/A die "bad netstat" if $?;
1N/A
1N/AWhile this is true on the surface, it's much more efficient to process the
1N/Afile one line or record at a time because then you don't have to read the
1N/Awhole thing into memory at once. It also gives you finer control of the
1N/Awhole process, letting you to kill off the child process early if you'd
1N/Alike.
1N/A
1N/ABe careful to check both the open() and the close() return values. If
1N/Ayou're I<writing> to a pipe, you should also trap SIGPIPE. Otherwise,
1N/Athink of what happens when you start up a pipe to a command that doesn't
1N/Aexist: the open() will in all likelihood succeed (it only reflects the
1N/Afork()'s success), but then your output will fail--spectacularly. Perl
1N/Acan't know whether the command worked because your command is actually
1N/Arunning in a separate process whose exec() might have failed. Therefore,
1N/Awhile readers of bogus commands return just a quick end of file, writers
1N/Ato bogus command will trigger a signal they'd better be prepared to
1N/Ahandle. Consider:
1N/A
1N/A open(FH, "|bogus") or die "can't fork: $!";
1N/A print FH "bang\n" or die "can't write: $!";
1N/A close FH or die "can't close: $!";
1N/A
1N/AThat won't blow up until the close, and it will blow up with a SIGPIPE.
1N/ATo catch it, you could use this:
1N/A
1N/A $SIG{PIPE} = 'IGNORE';
1N/A open(FH, "|bogus") or die "can't fork: $!";
1N/A print FH "bang\n" or die "can't write: $!";
1N/A close FH or die "can't close: status=$?";
1N/A
1N/A=head2 Filehandles
1N/A
1N/ABoth the main process and any child processes it forks share the same
1N/ASTDIN, STDOUT, and STDERR filehandles. If both processes try to access
1N/Athem at once, strange things can happen. You may also want to close
1N/Aor reopen the filehandles for the child. You can get around this by
1N/Aopening your pipe with open(), but on some systems this means that the
1N/Achild process cannot outlive the parent.
1N/A
1N/A=head2 Background Processes
1N/A
1N/AYou can run a command in the background with:
1N/A
1N/A system("cmd &");
1N/A
1N/AThe command's STDOUT and STDERR (and possibly STDIN, depending on your
1N/Ashell) will be the same as the parent's. You won't need to catch
1N/ASIGCHLD because of the double-fork taking place (see below for more
1N/Adetails).
1N/A
1N/A=head2 Complete Dissociation of Child from Parent
1N/A
1N/AIn some cases (starting server processes, for instance) you'll want to
1N/Acompletely dissociate the child process from the parent. This is
1N/Aoften called daemonization. A well behaved daemon will also chdir()
1N/Ato the root directory (so it doesn't prevent unmounting the filesystem
1N/Acontaining the directory from which it was launched) and redirect its
1N/Astandard file descriptors from and to F</dev/null> (so that random
1N/Aoutput doesn't wind up on the user's terminal).
1N/A
1N/A use POSIX 'setsid';
1N/A
1N/A sub daemonize {
1N/A chdir '/' or die "Can't chdir to /: $!";
1N/A open STDIN, '/dev/null' or die "Can't read /dev/null: $!";
1N/A open STDOUT, '>/dev/null'
1N/A or die "Can't write to /dev/null: $!";
1N/A defined(my $pid = fork) or die "Can't fork: $!";
1N/A exit if $pid;
1N/A setsid or die "Can't start a new session: $!";
1N/A open STDERR, '>&STDOUT' or die "Can't dup stdout: $!";
1N/A }
1N/A
1N/AThe fork() has to come before the setsid() to ensure that you aren't a
1N/Aprocess group leader (the setsid() will fail if you are). If your
1N/Asystem doesn't have the setsid() function, open F</dev/tty> and use the
1N/AC<TIOCNOTTY> ioctl() on it instead. See L<tty(4)> for details.
1N/A
1N/ANon-Unix users should check their Your_OS::Process module for other
1N/Asolutions.
1N/A
1N/A=head2 Safe Pipe Opens
1N/A
1N/AAnother interesting approach to IPC is making your single program go
1N/Amultiprocess and communicate between (or even amongst) yourselves. The
1N/Aopen() function will accept a file argument of either C<"-|"> or C<"|-">
1N/Ato do a very interesting thing: it forks a child connected to the
1N/Afilehandle you've opened. The child is running the same program as the
1N/Aparent. This is useful for safely opening a file when running under an
1N/Aassumed UID or GID, for example. If you open a pipe I<to> minus, you can
1N/Awrite to the filehandle you opened and your kid will find it in his
1N/ASTDIN. If you open a pipe I<from> minus, you can read from the filehandle
1N/Ayou opened whatever your kid writes to his STDOUT.
1N/A
1N/A use English '-no_match_vars';
1N/A my $sleep_count = 0;
1N/A
1N/A do {
1N/A $pid = open(KID_TO_WRITE, "|-");
1N/A unless (defined $pid) {
1N/A warn "cannot fork: $!";
1N/A die "bailing out" if $sleep_count++ > 6;
1N/A sleep 10;
1N/A }
1N/A } until defined $pid;
1N/A
1N/A if ($pid) { # parent
1N/A print KID_TO_WRITE @some_data;
1N/A close(KID_TO_WRITE) || warn "kid exited $?";
1N/A } else { # child
1N/A ($EUID, $EGID) = ($UID, $GID); # suid progs only
1N/A open (FILE, "> /safe/file")
1N/A || die "can't open /safe/file: $!";
1N/A while (<STDIN>) {
1N/A print FILE; # child's STDIN is parent's KID
1N/A }
1N/A exit; # don't forget this
1N/A }
1N/A
1N/AAnother common use for this construct is when you need to execute
1N/Asomething without the shell's interference. With system(), it's
1N/Astraightforward, but you can't use a pipe open or backticks safely.
1N/AThat's because there's no way to stop the shell from getting its hands on
1N/Ayour arguments. Instead, use lower-level control to call exec() directly.
1N/A
1N/AHere's a safe backtick or pipe open for read:
1N/A
1N/A # add error processing as above
1N/A $pid = open(KID_TO_READ, "-|");
1N/A
1N/A if ($pid) { # parent
1N/A while (<KID_TO_READ>) {
1N/A # do something interesting
1N/A }
1N/A close(KID_TO_READ) || warn "kid exited $?";
1N/A
1N/A } else { # child
1N/A ($EUID, $EGID) = ($UID, $GID); # suid only
1N/A exec($program, @options, @args)
1N/A || die "can't exec program: $!";
1N/A # NOTREACHED
1N/A }
1N/A
1N/A
1N/AAnd here's a safe pipe open for writing:
1N/A
1N/A # add error processing as above
1N/A $pid = open(KID_TO_WRITE, "|-");
1N/A $SIG{PIPE} = sub { die "whoops, $program pipe broke" };
1N/A
1N/A if ($pid) { # parent
1N/A for (@data) {
1N/A print KID_TO_WRITE;
1N/A }
1N/A close(KID_TO_WRITE) || warn "kid exited $?";
1N/A
1N/A } else { # child
1N/A ($EUID, $EGID) = ($UID, $GID);
1N/A exec($program, @options, @args)
1N/A || die "can't exec program: $!";
1N/A # NOTREACHED
1N/A }
1N/A
1N/ASince Perl 5.8.0, you can also use the list form of C<open> for pipes :
1N/Athe syntax
1N/A
1N/A open KID_PS, "-|", "ps", "aux" or die $!;
1N/A
1N/Aforks the ps(1) command (without spawning a shell, as there are more than
1N/Athree arguments to open()), and reads its standard output via the
1N/AC<KID_PS> filehandle. The corresponding syntax to read from command
1N/Apipes (with C<"|-"> in place of C<"-|">) is also implemented.
1N/A
1N/ANote that these operations are full Unix forks, which means they may not be
1N/Acorrectly implemented on alien systems. Additionally, these are not true
1N/Amultithreading. If you'd like to learn more about threading, see the
1N/AF<modules> file mentioned below in the SEE ALSO section.
1N/A
1N/A=head2 Bidirectional Communication with Another Process
1N/A
1N/AWhile this works reasonably well for unidirectional communication, what
1N/Aabout bidirectional communication? The obvious thing you'd like to do
1N/Adoesn't actually work:
1N/A
1N/A open(PROG_FOR_READING_AND_WRITING, "| some program |")
1N/A
1N/Aand if you forget to use the C<use warnings> pragma or the B<-w> flag,
1N/Athen you'll miss out entirely on the diagnostic message:
1N/A
1N/A Can't do bidirectional pipe at -e line 1.
1N/A
1N/AIf you really want to, you can use the standard open2() library function
1N/Ato catch both ends. There's also an open3() for tridirectional I/O so you
1N/Acan also catch your child's STDERR, but doing so would then require an
1N/Aawkward select() loop and wouldn't allow you to use normal Perl input
1N/Aoperations.
1N/A
1N/AIf you look at its source, you'll see that open2() uses low-level
1N/Aprimitives like Unix pipe() and exec() calls to create all the connections.
1N/AWhile it might have been slightly more efficient by using socketpair(), it
1N/Awould have then been even less portable than it already is. The open2()
1N/Aand open3() functions are unlikely to work anywhere except on a Unix
1N/Asystem or some other one purporting to be POSIX compliant.
1N/A
1N/AHere's an example of using open2():
1N/A
1N/A use FileHandle;
1N/A use IPC::Open2;
1N/A $pid = open2(*Reader, *Writer, "cat -u -n" );
1N/A print Writer "stuff\n";
1N/A $got = <Reader>;
1N/A
1N/AThe problem with this is that Unix buffering is really going to
1N/Aruin your day. Even though your C<Writer> filehandle is auto-flushed,
1N/Aand the process on the other end will get your data in a timely manner,
1N/Ayou can't usually do anything to force it to give it back to you
1N/Ain a similarly quick fashion. In this case, we could, because we
1N/Agave I<cat> a B<-u> flag to make it unbuffered. But very few Unix
1N/Acommands are designed to operate over pipes, so this seldom works
1N/Aunless you yourself wrote the program on the other end of the
1N/Adouble-ended pipe.
1N/A
1N/AA solution to this is the nonstandard F<Comm.pl> library. It uses
1N/Apseudo-ttys to make your program behave more reasonably:
1N/A
1N/A require 'Comm.pl';
1N/A $ph = open_proc('cat -n');
1N/A for (1..10) {
1N/A print $ph "a line\n";
1N/A print "got back ", scalar <$ph>;
1N/A }
1N/A
1N/AThis way you don't have to have control over the source code of the
1N/Aprogram you're using. The F<Comm> library also has expect()
1N/Aand interact() functions. Find the library (and we hope its
1N/Asuccessor F<IPC::Chat>) at your nearest CPAN archive as detailed
1N/Ain the SEE ALSO section below.
1N/A
1N/AThe newer Expect.pm module from CPAN also addresses this kind of thing.
1N/AThis module requires two other modules from CPAN: IO::Pty and IO::Stty.
1N/AIt sets up a pseudo-terminal to interact with programs that insist on
1N/Ausing talking to the terminal device driver. If your system is
1N/Aamongst those supported, this may be your best bet.
1N/A
1N/A=head2 Bidirectional Communication with Yourself
1N/A
1N/AIf you want, you may make low-level pipe() and fork()
1N/Ato stitch this together by hand. This example only
1N/Atalks to itself, but you could reopen the appropriate
1N/Ahandles to STDIN and STDOUT and call other processes.
1N/A
1N/A #!/usr/bin/perl -w
1N/A # pipe1 - bidirectional communication using two pipe pairs
1N/A # designed for the socketpair-challenged
1N/A use IO::Handle; # thousands of lines just for autoflush :-(
1N/A pipe(PARENT_RDR, CHILD_WTR); # XXX: failure?
1N/A pipe(CHILD_RDR, PARENT_WTR); # XXX: failure?
1N/A CHILD_WTR->autoflush(1);
1N/A PARENT_WTR->autoflush(1);
1N/A
1N/A if ($pid = fork) {
1N/A close PARENT_RDR; close PARENT_WTR;
1N/A print CHILD_WTR "Parent Pid $$ is sending this\n";
1N/A chomp($line = <CHILD_RDR>);
1N/A print "Parent Pid $$ just read this: `$line'\n";
1N/A close CHILD_RDR; close CHILD_WTR;
1N/A waitpid($pid,0);
1N/A } else {
1N/A die "cannot fork: $!" unless defined $pid;
1N/A close CHILD_RDR; close CHILD_WTR;
1N/A chomp($line = <PARENT_RDR>);
1N/A print "Child Pid $$ just read this: `$line'\n";
1N/A print PARENT_WTR "Child Pid $$ is sending this\n";
1N/A close PARENT_RDR; close PARENT_WTR;
1N/A exit;
1N/A }
1N/A
1N/ABut you don't actually have to make two pipe calls. If you
1N/Ahave the socketpair() system call, it will do this all for you.
1N/A
1N/A #!/usr/bin/perl -w
1N/A # pipe2 - bidirectional communication using socketpair
1N/A # "the best ones always go both ways"
1N/A
1N/A use Socket;
1N/A use IO::Handle; # thousands of lines just for autoflush :-(
1N/A # We say AF_UNIX because although *_LOCAL is the
1N/A # POSIX 1003.1g form of the constant, many machines
1N/A # still don't have it.
1N/A socketpair(CHILD, PARENT, AF_UNIX, SOCK_STREAM, PF_UNSPEC)
1N/A or die "socketpair: $!";
1N/A
1N/A CHILD->autoflush(1);
1N/A PARENT->autoflush(1);
1N/A
1N/A if ($pid = fork) {
1N/A close PARENT;
1N/A print CHILD "Parent Pid $$ is sending this\n";
1N/A chomp($line = <CHILD>);
1N/A print "Parent Pid $$ just read this: `$line'\n";
1N/A close CHILD;
1N/A waitpid($pid,0);
1N/A } else {
1N/A die "cannot fork: $!" unless defined $pid;
1N/A close CHILD;
1N/A chomp($line = <PARENT>);
1N/A print "Child Pid $$ just read this: `$line'\n";
1N/A print PARENT "Child Pid $$ is sending this\n";
1N/A close PARENT;
1N/A exit;
1N/A }
1N/A
1N/A=head1 Sockets: Client/Server Communication
1N/A
1N/AWhile not limited to Unix-derived operating systems (e.g., WinSock on PCs
1N/Aprovides socket support, as do some VMS libraries), you may not have
1N/Asockets on your system, in which case this section probably isn't going to do
1N/Ayou much good. With sockets, you can do both virtual circuits (i.e., TCP
1N/Astreams) and datagrams (i.e., UDP packets). You may be able to do even more
1N/Adepending on your system.
1N/A
1N/AThe Perl function calls for dealing with sockets have the same names as
1N/Athe corresponding system calls in C, but their arguments tend to differ
1N/Afor two reasons: first, Perl filehandles work differently than C file
1N/Adescriptors. Second, Perl already knows the length of its strings, so you
1N/Adon't need to pass that information.
1N/A
1N/AOne of the major problems with old socket code in Perl was that it used
1N/Ahard-coded values for some of the constants, which severely hurt
1N/Aportability. If you ever see code that does anything like explicitly
1N/Asetting C<$AF_INET = 2>, you know you're in for big trouble: An
1N/Aimmeasurably superior approach is to use the C<Socket> module, which more
1N/Areliably grants access to various constants and functions you'll need.
1N/A
1N/AIf you're not writing a server/client for an existing protocol like
1N/ANNTP or SMTP, you should give some thought to how your server will
1N/Aknow when the client has finished talking, and vice-versa. Most
1N/Aprotocols are based on one-line messages and responses (so one party
1N/Aknows the other has finished when a "\n" is received) or multi-line
1N/Amessages and responses that end with a period on an empty line
1N/A("\n.\n" terminates a message/response).
1N/A
1N/A=head2 Internet Line Terminators
1N/A
1N/AThe Internet line terminator is "\015\012". Under ASCII variants of
1N/AUnix, that could usually be written as "\r\n", but under other systems,
1N/A"\r\n" might at times be "\015\015\012", "\012\012\015", or something
1N/Acompletely different. The standards specify writing "\015\012" to be
1N/Aconformant (be strict in what you provide), but they also recommend
1N/Aaccepting a lone "\012" on input (but be lenient in what you require).
1N/AWe haven't always been very good about that in the code in this manpage,
1N/Abut unless you're on a Mac, you'll probably be ok.
1N/A
1N/A=head2 Internet TCP Clients and Servers
1N/A
1N/AUse Internet-domain sockets when you want to do client-server
1N/Acommunication that might extend to machines outside of your own system.
1N/A
1N/AHere's a sample TCP client using Internet-domain sockets:
1N/A
1N/A #!/usr/bin/perl -w
1N/A use strict;
1N/A use Socket;
1N/A my ($remote,$port, $iaddr, $paddr, $proto, $line);
1N/A
1N/A $remote = shift || 'localhost';
1N/A $port = shift || 2345; # random port
1N/A if ($port =~ /\D/) { $port = getservbyname($port, 'tcp') }
1N/A die "No port" unless $port;
1N/A $iaddr = inet_aton($remote) || die "no host: $remote";
1N/A $paddr = sockaddr_in($port, $iaddr);
1N/A
1N/A $proto = getprotobyname('tcp');
1N/A socket(SOCK, PF_INET, SOCK_STREAM, $proto) || die "socket: $!";
1N/A connect(SOCK, $paddr) || die "connect: $!";
1N/A while (defined($line = <SOCK>)) {
1N/A print $line;
1N/A }
1N/A
1N/A close (SOCK) || die "close: $!";
1N/A exit;
1N/A
1N/AAnd here's a corresponding server to go along with it. We'll
1N/Aleave the address as INADDR_ANY so that the kernel can choose
1N/Athe appropriate interface on multihomed hosts. If you want sit
1N/Aon a particular interface (like the external side of a gateway
1N/Aor firewall machine), you should fill this in with your real address
1N/Ainstead.
1N/A
1N/A #!/usr/bin/perl -Tw
1N/A use strict;
1N/A BEGIN { $ENV{PATH} = '/usr/ucb:/bin' }
1N/A use Socket;
1N/A use Carp;
1N/A my $EOL = "\015\012";
1N/A
1N/A sub logmsg { print "$0 $$: @_ at ", scalar localtime, "\n" }
1N/A
1N/A my $port = shift || 2345;
1N/A my $proto = getprotobyname('tcp');
1N/A
1N/A ($port) = $port =~ /^(\d+)$/ or die "invalid port";
1N/A
1N/A socket(Server, PF_INET, SOCK_STREAM, $proto) || die "socket: $!";
1N/A setsockopt(Server, SOL_SOCKET, SO_REUSEADDR,
1N/A pack("l", 1)) || die "setsockopt: $!";
1N/A bind(Server, sockaddr_in($port, INADDR_ANY)) || die "bind: $!";
1N/A listen(Server,SOMAXCONN) || die "listen: $!";
1N/A
1N/A logmsg "server started on port $port";
1N/A
1N/A my $paddr;
1N/A
1N/A $SIG{CHLD} = \&REAPER;
1N/A
1N/A for ( ; $paddr = accept(Client,Server); close Client) {
1N/A my($port,$iaddr) = sockaddr_in($paddr);
1N/A my $name = gethostbyaddr($iaddr,AF_INET);
1N/A
1N/A logmsg "connection from $name [",
1N/A inet_ntoa($iaddr), "]
1N/A at port $port";
1N/A
1N/A print Client "Hello there, $name, it's now ",
1N/A scalar localtime, $EOL;
1N/A }
1N/A
1N/AAnd here's a multithreaded version. It's multithreaded in that
1N/Alike most typical servers, it spawns (forks) a slave server to
1N/Ahandle the client request so that the master server can quickly
1N/Ago back to service a new client.
1N/A
1N/A #!/usr/bin/perl -Tw
1N/A use strict;
1N/A BEGIN { $ENV{PATH} = '/usr/ucb:/bin' }
1N/A use Socket;
1N/A use Carp;
1N/A my $EOL = "\015\012";
1N/A
1N/A sub spawn; # forward declaration
1N/A sub logmsg { print "$0 $$: @_ at ", scalar localtime, "\n" }
1N/A
1N/A my $port = shift || 2345;
1N/A my $proto = getprotobyname('tcp');
1N/A
1N/A ($port) = $port =~ /^(\d+)$/ or die "invalid port";
1N/A
1N/A socket(Server, PF_INET, SOCK_STREAM, $proto) || die "socket: $!";
1N/A setsockopt(Server, SOL_SOCKET, SO_REUSEADDR,
1N/A pack("l", 1)) || die "setsockopt: $!";
1N/A bind(Server, sockaddr_in($port, INADDR_ANY)) || die "bind: $!";
1N/A listen(Server,SOMAXCONN) || die "listen: $!";
1N/A
1N/A logmsg "server started on port $port";
1N/A
1N/A my $waitedpid = 0;
1N/A my $paddr;
1N/A
1N/A use POSIX ":sys_wait_h";
1N/A sub REAPER {
1N/A my $child;
1N/A while (($waitedpid = waitpid(-1,WNOHANG)) > 0) {
1N/A logmsg "reaped $waitedpid" . ($? ? " with exit $?" : '');
1N/A }
1N/A $SIG{CHLD} = \&REAPER; # loathe sysV
1N/A }
1N/A
1N/A $SIG{CHLD} = \&REAPER;
1N/A
1N/A for ( $waitedpid = 0;
1N/A ($paddr = accept(Client,Server)) || $waitedpid;
1N/A $waitedpid = 0, close Client)
1N/A {
1N/A next if $waitedpid and not $paddr;
1N/A my($port,$iaddr) = sockaddr_in($paddr);
1N/A my $name = gethostbyaddr($iaddr,AF_INET);
1N/A
1N/A logmsg "connection from $name [",
1N/A inet_ntoa($iaddr), "]
1N/A at port $port";
1N/A
1N/A spawn sub {
1N/A $|=1;
1N/A print "Hello there, $name, it's now ", scalar localtime, $EOL;
1N/A exec '/usr/games/fortune' # XXX: `wrong' line terminators
1N/A or confess "can't exec fortune: $!";
1N/A };
1N/A
1N/A }
1N/A
1N/A sub spawn {
1N/A my $coderef = shift;
1N/A
1N/A unless (@_ == 0 && $coderef && ref($coderef) eq 'CODE') {
1N/A confess "usage: spawn CODEREF";
1N/A }
1N/A
1N/A my $pid;
1N/A if (!defined($pid = fork)) {
1N/A logmsg "cannot fork: $!";
1N/A return;
1N/A } elsif ($pid) {
1N/A logmsg "begat $pid";
1N/A return; # I'm the parent
1N/A }
1N/A # else I'm the child -- go spawn
1N/A
1N/A open(STDIN, "<&Client") || die "can't dup client to stdin";
1N/A open(STDOUT, ">&Client") || die "can't dup client to stdout";
1N/A ## open(STDERR, ">&STDOUT") || die "can't dup stdout to stderr";
1N/A exit &$coderef();
1N/A }
1N/A
1N/AThis server takes the trouble to clone off a child version via fork() for
1N/Aeach incoming request. That way it can handle many requests at once,
1N/Awhich you might not always want. Even if you don't fork(), the listen()
1N/Awill allow that many pending connections. Forking servers have to be
1N/Aparticularly careful about cleaning up their dead children (called
1N/A"zombies" in Unix parlance), because otherwise you'll quickly fill up your
1N/Aprocess table.
1N/A
1N/AWe suggest that you use the B<-T> flag to use taint checking (see L<perlsec>)
1N/Aeven if we aren't running setuid or setgid. This is always a good idea
1N/Afor servers and other programs run on behalf of someone else (like CGI
1N/Ascripts), because it lessens the chances that people from the outside will
1N/Abe able to compromise your system.
1N/A
1N/ALet's look at another TCP client. This one connects to the TCP "time"
1N/Aservice on a number of different machines and shows how far their clocks
1N/Adiffer from the system on which it's being run:
1N/A
1N/A #!/usr/bin/perl -w
1N/A use strict;
1N/A use Socket;
1N/A
1N/A my $SECS_of_70_YEARS = 2208988800;
1N/A sub ctime { scalar localtime(shift) }
1N/A
1N/A my $iaddr = gethostbyname('localhost');
1N/A my $proto = getprotobyname('tcp');
1N/A my $port = getservbyname('time', 'tcp');
1N/A my $paddr = sockaddr_in(0, $iaddr);
1N/A my($host);
1N/A
1N/A $| = 1;
1N/A printf "%-24s %8s %s\n", "localhost", 0, ctime(time());
1N/A
1N/A foreach $host (@ARGV) {
1N/A printf "%-24s ", $host;
1N/A my $hisiaddr = inet_aton($host) || die "unknown host";
1N/A my $hispaddr = sockaddr_in($port, $hisiaddr);
1N/A socket(SOCKET, PF_INET, SOCK_STREAM, $proto) || die "socket: $!";
1N/A connect(SOCKET, $hispaddr) || die "bind: $!";
1N/A my $rtime = ' ';
1N/A read(SOCKET, $rtime, 4);
1N/A close(SOCKET);
1N/A my $histime = unpack("N", $rtime) - $SECS_of_70_YEARS ;
1N/A printf "%8d %s\n", $histime - time, ctime($histime);
1N/A }
1N/A
1N/A=head2 Unix-Domain TCP Clients and Servers
1N/A
1N/AThat's fine for Internet-domain clients and servers, but what about local
1N/Acommunications? While you can use the same setup, sometimes you don't
1N/Awant to. Unix-domain sockets are local to the current host, and are often
1N/Aused internally to implement pipes. Unlike Internet domain sockets, Unix
1N/Adomain sockets can show up in the file system with an ls(1) listing.
1N/A
1N/A % ls -l /dev/log
1N/A srw-rw-rw- 1 root 0 Oct 31 07:23 /dev/log
1N/A
1N/AYou can test for these with Perl's B<-S> file test:
1N/A
1N/A unless ( -S '/dev/log' ) {
1N/A die "something's wicked with the log system";
1N/A }
1N/A
1N/AHere's a sample Unix-domain client:
1N/A
1N/A #!/usr/bin/perl -w
1N/A use Socket;
1N/A use strict;
1N/A my ($rendezvous, $line);
1N/A
1N/A $rendezvous = shift || 'catsock';
1N/A socket(SOCK, PF_UNIX, SOCK_STREAM, 0) || die "socket: $!";
1N/A connect(SOCK, sockaddr_un($rendezvous)) || die "connect: $!";
1N/A while (defined($line = <SOCK>)) {
1N/A print $line;
1N/A }
1N/A exit;
1N/A
1N/AAnd here's a corresponding server. You don't have to worry about silly
1N/Anetwork terminators here because Unix domain sockets are guaranteed
1N/Ato be on the localhost, and thus everything works right.
1N/A
1N/A #!/usr/bin/perl -Tw
1N/A use strict;
1N/A use Socket;
1N/A use Carp;
1N/A
1N/A BEGIN { $ENV{PATH} = '/usr/ucb:/bin' }
1N/A sub spawn; # forward declaration
1N/A sub logmsg { print "$0 $$: @_ at ", scalar localtime, "\n" }
1N/A
1N/A my $NAME = 'catsock';
1N/A my $uaddr = sockaddr_un($NAME);
1N/A my $proto = getprotobyname('tcp');
1N/A
1N/A socket(Server,PF_UNIX,SOCK_STREAM,0) || die "socket: $!";
1N/A unlink($NAME);
1N/A bind (Server, $uaddr) || die "bind: $!";
1N/A listen(Server,SOMAXCONN) || die "listen: $!";
1N/A
1N/A logmsg "server started on $NAME";
1N/A
1N/A my $waitedpid;
1N/A
1N/A use POSIX ":sys_wait_h";
1N/A sub REAPER {
1N/A my $child;
1N/A while (($waitedpid = waitpid(-1,WNOHANG)) > 0) {
1N/A logmsg "reaped $waitedpid" . ($? ? " with exit $?" : '');
1N/A }
1N/A $SIG{CHLD} = \&REAPER; # loathe sysV
1N/A }
1N/A
1N/A $SIG{CHLD} = \&REAPER;
1N/A
1N/A
1N/A for ( $waitedpid = 0;
1N/A accept(Client,Server) || $waitedpid;
1N/A $waitedpid = 0, close Client)
1N/A {
1N/A next if $waitedpid;
1N/A logmsg "connection on $NAME";
1N/A spawn sub {
1N/A print "Hello there, it's now ", scalar localtime, "\n";
1N/A exec '/usr/games/fortune' or die "can't exec fortune: $!";
1N/A };
1N/A }
1N/A
1N/A sub spawn {
1N/A my $coderef = shift;
1N/A
1N/A unless (@_ == 0 && $coderef && ref($coderef) eq 'CODE') {
1N/A confess "usage: spawn CODEREF";
1N/A }
1N/A
1N/A my $pid;
1N/A if (!defined($pid = fork)) {
1N/A logmsg "cannot fork: $!";
1N/A return;
1N/A } elsif ($pid) {
1N/A logmsg "begat $pid";
1N/A return; # I'm the parent
1N/A }
1N/A # else I'm the child -- go spawn
1N/A
1N/A open(STDIN, "<&Client") || die "can't dup client to stdin";
1N/A open(STDOUT, ">&Client") || die "can't dup client to stdout";
1N/A ## open(STDERR, ">&STDOUT") || die "can't dup stdout to stderr";
1N/A exit &$coderef();
1N/A }
1N/A
1N/AAs you see, it's remarkably similar to the Internet domain TCP server, so
1N/Amuch so, in fact, that we've omitted several duplicate functions--spawn(),
1N/Alogmsg(), ctime(), and REAPER()--which are exactly the same as in the
1N/Aother server.
1N/A
1N/ASo why would you ever want to use a Unix domain socket instead of a
1N/Asimpler named pipe? Because a named pipe doesn't give you sessions. You
1N/Acan't tell one process's data from another's. With socket programming,
1N/Ayou get a separate session for each client: that's why accept() takes two
1N/Aarguments.
1N/A
1N/AFor example, let's say that you have a long running database server daemon
1N/Athat you want folks from the World Wide Web to be able to access, but only
1N/Aif they go through a CGI interface. You'd have a small, simple CGI
1N/Aprogram that does whatever checks and logging you feel like, and then acts
1N/Aas a Unix-domain client and connects to your private server.
1N/A
1N/A=head1 TCP Clients with IO::Socket
1N/A
1N/AFor those preferring a higher-level interface to socket programming, the
1N/AIO::Socket module provides an object-oriented approach. IO::Socket is
1N/Aincluded as part of the standard Perl distribution as of the 5.004
1N/Arelease. If you're running an earlier version of Perl, just fetch
1N/AIO::Socket from CPAN, where you'll also find modules providing easy
1N/Ainterfaces to the following systems: DNS, FTP, Ident (RFC 931), NIS and
1N/ANISPlus, NNTP, Ping, POP3, SMTP, SNMP, SSLeay, Telnet, and Time--just
1N/Ato name a few.
1N/A
1N/A=head2 A Simple Client
1N/A
1N/AHere's a client that creates a TCP connection to the "daytime"
1N/Aservice at port 13 of the host name "localhost" and prints out everything
1N/Athat the server there cares to provide.
1N/A
1N/A #!/usr/bin/perl -w
1N/A use IO::Socket;
1N/A $remote = IO::Socket::INET->new(
1N/A Proto => "tcp",
1N/A PeerAddr => "localhost",
1N/A PeerPort => "daytime(13)",
1N/A )
1N/A or die "cannot connect to daytime port at localhost";
1N/A while ( <$remote> ) { print }
1N/A
1N/AWhen you run this program, you should get something back that
1N/Alooks like this:
1N/A
1N/A Wed May 14 08:40:46 MDT 1997
1N/A
1N/AHere are what those parameters to the C<new> constructor mean:
1N/A
1N/A=over 4
1N/A
1N/A=item C<Proto>
1N/A
1N/AThis is which protocol to use. In this case, the socket handle returned
1N/Awill be connected to a TCP socket, because we want a stream-oriented
1N/Aconnection, that is, one that acts pretty much like a plain old file.
1N/ANot all sockets are this of this type. For example, the UDP protocol
1N/Acan be used to make a datagram socket, used for message-passing.
1N/A
1N/A=item C<PeerAddr>
1N/A
1N/AThis is the name or Internet address of the remote host the server is
1N/Arunning on. We could have specified a longer name like C<"www.perl.com">,
1N/Aor an address like C<"204.148.40.9">. For demonstration purposes, we've
1N/Aused the special hostname C<"localhost">, which should always mean the
1N/Acurrent machine you're running on. The corresponding Internet address
1N/Afor localhost is C<"127.1">, if you'd rather use that.
1N/A
1N/A=item C<PeerPort>
1N/A
1N/AThis is the service name or port number we'd like to connect to.
1N/AWe could have gotten away with using just C<"daytime"> on systems with a
1N/Awell-configured system services file,[FOOTNOTE: The system services file
1N/Ais in I</etc/services> under Unix] but just in case, we've specified the
1N/Aport number (13) in parentheses. Using just the number would also have
1N/Aworked, but constant numbers make careful programmers nervous.
1N/A
1N/A=back
1N/A
1N/ANotice how the return value from the C<new> constructor is used as
1N/Aa filehandle in the C<while> loop? That's what's called an indirect
1N/Afilehandle, a scalar variable containing a filehandle. You can use
1N/Ait the same way you would a normal filehandle. For example, you
1N/Acan read one line from it this way:
1N/A
1N/A $line = <$handle>;
1N/A
1N/Aall remaining lines from is this way:
1N/A
1N/A @lines = <$handle>;
1N/A
1N/Aand send a line of data to it this way:
1N/A
1N/A print $handle "some data\n";
1N/A
1N/A=head2 A Webget Client
1N/A
1N/AHere's a simple client that takes a remote host to fetch a document
1N/Afrom, and then a list of documents to get from that host. This is a
1N/Amore interesting client than the previous one because it first sends
1N/Asomething to the server before fetching the server's response.
1N/A
1N/A #!/usr/bin/perl -w
1N/A use IO::Socket;
1N/A unless (@ARGV > 1) { die "usage: $0 host document ..." }
1N/A $host = shift(@ARGV);
1N/A $EOL = "\015\012";
1N/A $BLANK = $EOL x 2;
1N/A foreach $document ( @ARGV ) {
1N/A $remote = IO::Socket::INET->new( Proto => "tcp",
1N/A PeerAddr => $host,
1N/A PeerPort => "http(80)",
1N/A );
1N/A unless ($remote) { die "cannot connect to http daemon on $host" }
1N/A $remote->autoflush(1);
1N/A print $remote "GET $document HTTP/1.0" . $BLANK;
1N/A while ( <$remote> ) { print }
1N/A close $remote;
1N/A }
1N/A
1N/AThe web server handing the "http" service, which is assumed to be at
1N/Aits standard port, number 80. If the web server you're trying to
1N/Aconnect to is at a different port (like 1080 or 8080), you should specify
1N/Aas the named-parameter pair, C<< PeerPort => 8080 >>. The C<autoflush>
1N/Amethod is used on the socket because otherwise the system would buffer
1N/Aup the output we sent it. (If you're on a Mac, you'll also need to
1N/Achange every C<"\n"> in your code that sends data over the network to
1N/Abe a C<"\015\012"> instead.)
1N/A
1N/AConnecting to the server is only the first part of the process: once you
1N/Ahave the connection, you have to use the server's language. Each server
1N/Aon the network has its own little command language that it expects as
1N/Ainput. The string that we send to the server starting with "GET" is in
1N/AHTTP syntax. In this case, we simply request each specified document.
1N/AYes, we really are making a new connection for each document, even though
1N/Ait's the same host. That's the way you always used to have to speak HTTP.
1N/ARecent versions of web browsers may request that the remote server leave
1N/Athe connection open a little while, but the server doesn't have to honor
1N/Asuch a request.
1N/A
1N/AHere's an example of running that program, which we'll call I<webget>:
1N/A
1N/A % webget www.perl.com /guanaco.html
1N/A HTTP/1.1 404 File Not Found
1N/A Date: Thu, 08 May 1997 18:02:32 GMT
1N/A Server: Apache/1.2b6
1N/A Connection: close
1N/A Content-type: text/html
1N/A
1N/A <HEAD><TITLE>404 File Not Found</TITLE></HEAD>
1N/A <BODY><H1>File Not Found</H1>
1N/A The requested URL /guanaco.html was not found on this server.<P>
1N/A </BODY>
1N/A
1N/AOk, so that's not very interesting, because it didn't find that
1N/Aparticular document. But a long response wouldn't have fit on this page.
1N/A
1N/AFor a more fully-featured version of this program, you should look to
1N/Athe I<lwp-request> program included with the LWP modules from CPAN.
1N/A
1N/A=head2 Interactive Client with IO::Socket
1N/A
1N/AWell, that's all fine if you want to send one command and get one answer,
1N/Abut what about setting up something fully interactive, somewhat like
1N/Athe way I<telnet> works? That way you can type a line, get the answer,
1N/Atype a line, get the answer, etc.
1N/A
1N/AThis client is more complicated than the two we've done so far, but if
1N/Ayou're on a system that supports the powerful C<fork> call, the solution
1N/Aisn't that rough. Once you've made the connection to whatever service
1N/Ayou'd like to chat with, call C<fork> to clone your process. Each of
1N/Athese two identical process has a very simple job to do: the parent
1N/Acopies everything from the socket to standard output, while the child
1N/Asimultaneously copies everything from standard input to the socket.
1N/ATo accomplish the same thing using just one process would be I<much>
1N/Aharder, because it's easier to code two processes to do one thing than it
1N/Ais to code one process to do two things. (This keep-it-simple principle
1N/Aa cornerstones of the Unix philosophy, and good software engineering as
1N/Awell, which is probably why it's spread to other systems.)
1N/A
1N/AHere's the code:
1N/A
1N/A #!/usr/bin/perl -w
1N/A use strict;
1N/A use IO::Socket;
1N/A my ($host, $port, $kidpid, $handle, $line);
1N/A
1N/A unless (@ARGV == 2) { die "usage: $0 host port" }
1N/A ($host, $port) = @ARGV;
1N/A
1N/A # create a tcp connection to the specified host and port
1N/A $handle = IO::Socket::INET->new(Proto => "tcp",
1N/A PeerAddr => $host,
1N/A PeerPort => $port)
1N/A or die "can't connect to port $port on $host: $!";
1N/A
1N/A $handle->autoflush(1); # so output gets there right away
1N/A print STDERR "[Connected to $host:$port]\n";
1N/A
1N/A # split the program into two processes, identical twins
1N/A die "can't fork: $!" unless defined($kidpid = fork());
1N/A
1N/A # the if{} block runs only in the parent process
1N/A if ($kidpid) {
1N/A # copy the socket to standard output
1N/A while (defined ($line = <$handle>)) {
1N/A print STDOUT $line;
1N/A }
1N/A kill("TERM", $kidpid); # send SIGTERM to child
1N/A }
1N/A # the else{} block runs only in the child process
1N/A else {
1N/A # copy standard input to the socket
1N/A while (defined ($line = <STDIN>)) {
1N/A print $handle $line;
1N/A }
1N/A }
1N/A
1N/AThe C<kill> function in the parent's C<if> block is there to send a
1N/Asignal to our child process (current running in the C<else> block)
1N/Aas soon as the remote server has closed its end of the connection.
1N/A
1N/AIf the remote server sends data a byte at time, and you need that
1N/Adata immediately without waiting for a newline (which might not happen),
1N/Ayou may wish to replace the C<while> loop in the parent with the
1N/Afollowing:
1N/A
1N/A my $byte;
1N/A while (sysread($handle, $byte, 1) == 1) {
1N/A print STDOUT $byte;
1N/A }
1N/A
1N/AMaking a system call for each byte you want to read is not very efficient
1N/A(to put it mildly) but is the simplest to explain and works reasonably
1N/Awell.
1N/A
1N/A=head1 TCP Servers with IO::Socket
1N/A
1N/AAs always, setting up a server is little bit more involved than running a client.
1N/AThe model is that the server creates a special kind of socket that
1N/Adoes nothing but listen on a particular port for incoming connections.
1N/AIt does this by calling the C<< IO::Socket::INET->new() >> method with
1N/Aslightly different arguments than the client did.
1N/A
1N/A=over 4
1N/A
1N/A=item Proto
1N/A
1N/AThis is which protocol to use. Like our clients, we'll
1N/Astill specify C<"tcp"> here.
1N/A
1N/A=item LocalPort
1N/A
1N/AWe specify a local
1N/Aport in the C<LocalPort> argument, which we didn't do for the client.
1N/AThis is service name or port number for which you want to be the
1N/Aserver. (Under Unix, ports under 1024 are restricted to the
1N/Asuperuser.) In our sample, we'll use port 9000, but you can use
1N/Aany port that's not currently in use on your system. If you try
1N/Ato use one already in used, you'll get an "Address already in use"
1N/Amessage. Under Unix, the C<netstat -a> command will show
1N/Awhich services current have servers.
1N/A
1N/A=item Listen
1N/A
1N/AThe C<Listen> parameter is set to the maximum number of
1N/Apending connections we can accept until we turn away incoming clients.
1N/AThink of it as a call-waiting queue for your telephone.
1N/AThe low-level Socket module has a special symbol for the system maximum, which
1N/Ais SOMAXCONN.
1N/A
1N/A=item Reuse
1N/A
1N/AThe C<Reuse> parameter is needed so that we restart our server
1N/Amanually without waiting a few minutes to allow system buffers to
1N/Aclear out.
1N/A
1N/A=back
1N/A
1N/AOnce the generic server socket has been created using the parameters
1N/Alisted above, the server then waits for a new client to connect
1N/Ato it. The server blocks in the C<accept> method, which eventually accepts a
1N/Abidirectional connection from the remote client. (Make sure to autoflush
1N/Athis handle to circumvent buffering.)
1N/A
1N/ATo add to user-friendliness, our server prompts the user for commands.
1N/AMost servers don't do this. Because of the prompt without a newline,
1N/Ayou'll have to use the C<sysread> variant of the interactive client above.
1N/A
1N/AThis server accepts one of five different commands, sending output
1N/Aback to the client. Note that unlike most network servers, this one
1N/Aonly handles one incoming client at a time. Multithreaded servers are
1N/Acovered in Chapter 6 of the Camel.
1N/A
1N/AHere's the code. We'll
1N/A
1N/A #!/usr/bin/perl -w
1N/A use IO::Socket;
1N/A use Net::hostent; # for OO version of gethostbyaddr
1N/A
1N/A $PORT = 9000; # pick something not in use
1N/A
1N/A $server = IO::Socket::INET->new( Proto => 'tcp',
1N/A LocalPort => $PORT,
1N/A Listen => SOMAXCONN,
1N/A Reuse => 1);
1N/A
1N/A die "can't setup server" unless $server;
1N/A print "[Server $0 accepting clients]\n";
1N/A
1N/A while ($client = $server->accept()) {
1N/A $client->autoflush(1);
1N/A print $client "Welcome to $0; type help for command list.\n";
1N/A $hostinfo = gethostbyaddr($client->peeraddr);
1N/A printf "[Connect from %s]\n", $hostinfo ? $hostinfo->name : $client->peerhost;
1N/A print $client "Command? ";
1N/A while ( <$client>) {
1N/A next unless /\S/; # blank line
1N/A if (/quit|exit/i) { last; }
1N/A elsif (/date|time/i) { printf $client "%s\n", scalar localtime; }
1N/A elsif (/who/i ) { print $client `who 2>&1`; }
1N/A elsif (/cookie/i ) { print $client `/usr/games/fortune 2>&1`; }
1N/A elsif (/motd/i ) { print $client `cat /etc/motd 2>&1`; }
1N/A else {
1N/A print $client "Commands: quit date who cookie motd\n";
1N/A }
1N/A } continue {
1N/A print $client "Command? ";
1N/A }
1N/A close $client;
1N/A }
1N/A
1N/A=head1 UDP: Message Passing
1N/A
1N/AAnother kind of client-server setup is one that uses not connections, but
1N/Amessages. UDP communications involve much lower overhead but also provide
1N/Aless reliability, as there are no promises that messages will arrive at
1N/Aall, let alone in order and unmangled. Still, UDP offers some advantages
1N/Aover TCP, including being able to "broadcast" or "multicast" to a whole
1N/Abunch of destination hosts at once (usually on your local subnet). If you
1N/Afind yourself overly concerned about reliability and start building checks
1N/Ainto your message system, then you probably should use just TCP to start
1N/Awith.
1N/A
1N/ANote that UDP datagrams are I<not> a bytestream and should not be treated
1N/Aas such. This makes using I/O mechanisms with internal buffering
1N/Alike stdio (i.e. print() and friends) especially cumbersome. Use syswrite(),
1N/Aor better send(), like in the example below.
1N/A
1N/AHere's a UDP program similar to the sample Internet TCP client given
1N/Aearlier. However, instead of checking one host at a time, the UDP version
1N/Awill check many of them asynchronously by simulating a multicast and then
1N/Ausing select() to do a timed-out wait for I/O. To do something similar
1N/Awith TCP, you'd have to use a different socket handle for each host.
1N/A
1N/A #!/usr/bin/perl -w
1N/A use strict;
1N/A use Socket;
1N/A use Sys::Hostname;
1N/A
1N/A my ( $count, $hisiaddr, $hispaddr, $histime,
1N/A $host, $iaddr, $paddr, $port, $proto,
1N/A $rin, $rout, $rtime, $SECS_of_70_YEARS);
1N/A
1N/A $SECS_of_70_YEARS = 2208988800;
1N/A
1N/A $iaddr = gethostbyname(hostname());
1N/A $proto = getprotobyname('udp');
1N/A $port = getservbyname('time', 'udp');
1N/A $paddr = sockaddr_in(0, $iaddr); # 0 means let kernel pick
1N/A
1N/A socket(SOCKET, PF_INET, SOCK_DGRAM, $proto) || die "socket: $!";
1N/A bind(SOCKET, $paddr) || die "bind: $!";
1N/A
1N/A $| = 1;
1N/A printf "%-12s %8s %s\n", "localhost", 0, scalar localtime time;
1N/A $count = 0;
1N/A for $host (@ARGV) {
1N/A $count++;
1N/A $hisiaddr = inet_aton($host) || die "unknown host";
1N/A $hispaddr = sockaddr_in($port, $hisiaddr);
1N/A defined(send(SOCKET, 0, 0, $hispaddr)) || die "send $host: $!";
1N/A }
1N/A
1N/A $rin = '';
1N/A vec($rin, fileno(SOCKET), 1) = 1;
1N/A
1N/A # timeout after 10.0 seconds
1N/A while ($count && select($rout = $rin, undef, undef, 10.0)) {
1N/A $rtime = '';
1N/A ($hispaddr = recv(SOCKET, $rtime, 4, 0)) || die "recv: $!";
1N/A ($port, $hisiaddr) = sockaddr_in($hispaddr);
1N/A $host = gethostbyaddr($hisiaddr, AF_INET);
1N/A $histime = unpack("N", $rtime) - $SECS_of_70_YEARS ;
1N/A printf "%-12s ", $host;
1N/A printf "%8d %s\n", $histime - time, scalar localtime($histime);
1N/A $count--;
1N/A }
1N/A
1N/ANote that this example does not include any retries and may consequently
1N/Afail to contact a reachable host. The most prominent reason for this
1N/Ais congestion of the queues on the sending host if the number of
1N/Alist of hosts to contact is sufficiently large.
1N/A
1N/A=head1 SysV IPC
1N/A
1N/AWhile System V IPC isn't so widely used as sockets, it still has some
1N/Ainteresting uses. You can't, however, effectively use SysV IPC or
1N/ABerkeley mmap() to have shared memory so as to share a variable amongst
1N/Aseveral processes. That's because Perl would reallocate your string when
1N/Ayou weren't wanting it to.
1N/A
1N/AHere's a small example showing shared memory usage.
1N/A
1N/A use IPC::SysV qw(IPC_PRIVATE IPC_RMID S_IRWXU);
1N/A
1N/A $size = 2000;
1N/A $id = shmget(IPC_PRIVATE, $size, S_IRWXU) || die "$!";
1N/A print "shm key $id\n";
1N/A
1N/A $message = "Message #1";
1N/A shmwrite($id, $message, 0, 60) || die "$!";
1N/A print "wrote: '$message'\n";
1N/A shmread($id, $buff, 0, 60) || die "$!";
1N/A print "read : '$buff'\n";
1N/A
1N/A # the buffer of shmread is zero-character end-padded.
1N/A substr($buff, index($buff, "\0")) = '';
1N/A print "un" unless $buff eq $message;
1N/A print "swell\n";
1N/A
1N/A print "deleting shm $id\n";
1N/A shmctl($id, IPC_RMID, 0) || die "$!";
1N/A
1N/AHere's an example of a semaphore:
1N/A
1N/A use IPC::SysV qw(IPC_CREAT);
1N/A
1N/A $IPC_KEY = 1234;
1N/A $id = semget($IPC_KEY, 10, 0666 | IPC_CREAT ) || die "$!";
1N/A print "shm key $id\n";
1N/A
1N/APut this code in a separate file to be run in more than one process.
1N/ACall the file F<take>:
1N/A
1N/A # create a semaphore
1N/A
1N/A $IPC_KEY = 1234;
1N/A $id = semget($IPC_KEY, 0 , 0 );
1N/A die if !defined($id);
1N/A
1N/A $semnum = 0;
1N/A $semflag = 0;
1N/A
1N/A # 'take' semaphore
1N/A # wait for semaphore to be zero
1N/A $semop = 0;
1N/A $opstring1 = pack("s!s!s!", $semnum, $semop, $semflag);
1N/A
1N/A # Increment the semaphore count
1N/A $semop = 1;
1N/A $opstring2 = pack("s!s!s!", $semnum, $semop, $semflag);
1N/A $opstring = $opstring1 . $opstring2;
1N/A
1N/A semop($id,$opstring) || die "$!";
1N/A
1N/APut this code in a separate file to be run in more than one process.
1N/ACall this file F<give>:
1N/A
1N/A # 'give' the semaphore
1N/A # run this in the original process and you will see
1N/A # that the second process continues
1N/A
1N/A $IPC_KEY = 1234;
1N/A $id = semget($IPC_KEY, 0, 0);
1N/A die if !defined($id);
1N/A
1N/A $semnum = 0;
1N/A $semflag = 0;
1N/A
1N/A # Decrement the semaphore count
1N/A $semop = -1;
1N/A $opstring = pack("s!s!s!", $semnum, $semop, $semflag);
1N/A
1N/A semop($id,$opstring) || die "$!";
1N/A
1N/AThe SysV IPC code above was written long ago, and it's definitely
1N/Aclunky looking. For a more modern look, see the IPC::SysV module
1N/Awhich is included with Perl starting from Perl 5.005.
1N/A
1N/AA small example demonstrating SysV message queues:
1N/A
1N/A use IPC::SysV qw(IPC_PRIVATE IPC_RMID IPC_CREAT S_IRWXU);
1N/A
1N/A my $id = msgget(IPC_PRIVATE, IPC_CREAT | S_IRWXU);
1N/A
1N/A my $sent = "message";
1N/A my $type_sent = 1234;
1N/A my $rcvd;
1N/A my $type_rcvd;
1N/A
1N/A if (defined $id) {
1N/A if (msgsnd($id, pack("l! a*", $type_sent, $sent), 0)) {
1N/A if (msgrcv($id, $rcvd, 60, 0, 0)) {
1N/A ($type_rcvd, $rcvd) = unpack("l! a*", $rcvd);
1N/A if ($rcvd eq $sent) {
1N/A print "okay\n";
1N/A } else {
1N/A print "not okay\n";
1N/A }
1N/A } else {
1N/A die "# msgrcv failed\n";
1N/A }
1N/A } else {
1N/A die "# msgsnd failed\n";
1N/A }
1N/A msgctl($id, IPC_RMID, 0) || die "# msgctl failed: $!\n";
1N/A } else {
1N/A die "# msgget failed\n";
1N/A }
1N/A
1N/A=head1 NOTES
1N/A
1N/AMost of these routines quietly but politely return C<undef> when they
1N/Afail instead of causing your program to die right then and there due to
1N/Aan uncaught exception. (Actually, some of the new I<Socket> conversion
1N/Afunctions croak() on bad arguments.) It is therefore essential to
1N/Acheck return values from these functions. Always begin your socket
1N/Aprograms this way for optimal success, and don't forget to add B<-T>
1N/Ataint checking flag to the #! line for servers:
1N/A
1N/A #!/usr/bin/perl -Tw
1N/A use strict;
1N/A use sigtrap;
1N/A use Socket;
1N/A
1N/A=head1 BUGS
1N/A
1N/AAll these routines create system-specific portability problems. As noted
1N/Aelsewhere, Perl is at the mercy of your C libraries for much of its system
1N/Abehaviour. It's probably safest to assume broken SysV semantics for
1N/Asignals and to stick with simple TCP and UDP socket operations; e.g., don't
1N/Atry to pass open file descriptors over a local UDP datagram socket if you
1N/Awant your code to stand a chance of being portable.
1N/A
1N/AAs mentioned in the signals section, because few vendors provide C
1N/Alibraries that are safely re-entrant, the prudent programmer will do
1N/Alittle else within a handler beyond setting a numeric variable that
1N/Aalready exists; or, if locked into a slow (restarting) system call,
1N/Ausing die() to raise an exception and longjmp(3) out. In fact, even
1N/Athese may in some cases cause a core dump. It's probably best to avoid
1N/Asignals except where they are absolutely inevitable. This
1N/Awill be addressed in a future release of Perl.
1N/A
1N/A=head1 AUTHOR
1N/A
1N/ATom Christiansen, with occasional vestiges of Larry Wall's original
1N/Aversion and suggestions from the Perl Porters.
1N/A
1N/A=head1 SEE ALSO
1N/A
1N/AThere's a lot more to networking than this, but this should get you
1N/Astarted.
1N/A
1N/AFor intrepid programmers, the indispensable textbook is I<Unix
1N/ANetwork Programming, 2nd Edition, Volume 1> by W. Richard Stevens
1N/A(published by Prentice-Hall). Note that most books on networking
1N/Aaddress the subject from the perspective of a C programmer; translation
1N/Ato Perl is left as an exercise for the reader.
1N/A
1N/AThe IO::Socket(3) manpage describes the object library, and the Socket(3)
1N/Amanpage describes the low-level interface to sockets. Besides the obvious
1N/Afunctions in L<perlfunc>, you should also check out the F<modules> file
1N/Aat your nearest CPAN site. (See L<perlmodlib> or best yet, the F<Perl
1N/AFAQ> for a description of what CPAN is and where to get it.)
1N/A
1N/ASection 5 of the F<modules> file is devoted to "Networking, Device Control
1N/A(modems), and Interprocess Communication", and contains numerous unbundled
1N/Amodules numerous networking modules, Chat and Expect operations, CGI
1N/Aprogramming, DCE, FTP, IPC, NNTP, Proxy, Ptty, RPC, SNMP, SMTP, Telnet,
1N/AThreads, and ToolTalk--just to name a few.