*nix Documentation Project
·  Home
 +   man pages
·  Linux HOWTOs
·  FreeBSD Tips
·  *niX Forums

  man pages->IRIX man pages -> perlipc (1)              
Title
Content
Arch
Section
 

t(3)

Contents


PERLIPC(1)							    PERLIPC(1)


NAME    [Toc]    [Back]

     perlipc - Perl interprocess communication (signals, fifos,	pipes, safe
     subprocesses, sockets, and	semaphores)

DESCRIPTION    [Toc]    [Back]

     The basic IPC facilities of Perl are built	out of the good	old Unix
     signals, named pipes, pipe	opens, the Berkeley socket routines, and SysV
     IPC calls.	 Each is used in slightly different situations.

Signals    [Toc]    [Back]

     Perl uses a simple	signal handling	model: the %SIG	hash contains names or
     references	of user-installed signal handlers.  These handlers will	be
     called with an argument which is the name of the signal that triggered
     it.  A signal may be generated intentionally from a particular keyboard
     sequence like control-C or	control-Z, sent	to you from another process,
     or	triggered automatically	by the kernel when special events transpire,
     like a child process exiting, your	process	running	out of stack space, or
     hitting file size limit.

     For example, to trap an interrupt signal, set up a	handler	like this.  Do
     as	little as you possibly can in your handler; notice how all we do is
     set a global variable and then raise an exception.	 That's	because	on
     most systems, libraries are not re-entrant; particularly, memory
     allocation	and I/O	routines are not.  That	means that doing nearly
     anything in your handler could in theory trigger a	memory fault and
     subsequent	core dump.

	 sub catch_zap {
	     my	$signame = shift;
	     $shucks++;
	     die "Somebody sent	me a SIG$signame";
	 }
	 $SIG{INT} = 'catch_zap';  # could fail	in modules
	 $SIG{INT} = \&catch_zap;  # best strategy

     The names of the signals are the ones listed out by kill -l on your
     system, or	you can	retrieve them from the Config module.  Set up an
     @signame list indexed by number to	get the	name and a %signo table
     indexed by	name to	get the	number:

	 use Config;
	 defined $Config{sig_name} || die "No sigs?";
	 foreach $name (split('	', $Config{sig_name})) {
	     $signo{$name} = $i;
	     $signame[$i] = $name;
	     $i++;
	 }

     So	to check whether signal	17 and SIGALRM were the	same, do just this:






									Page 1






PERLIPC(1)							    PERLIPC(1)



	 print "signal #17 = $signame[17]\n";
	 if ($signo{ALRM}) {
	     print "SIGALRM is $signo{ALRM}\n";
	 }

     You may also choose to assign the strings 'IGNORE'	or 'DEFAULT' as	the
     handler, in which case Perl will try to discard the signal	or do the
     default thing.  Some signals can be neither trapped nor ignored, such as
     the KILL and STOP (but not	the TSTP) signals.  One	strategy for
     temporarily ignoring signals is to	use a local() statement, which will be
     automatically restored once your block is exited.	(Remember that local()
     values are	"inherited" by functions called	from within that block.)

	 sub precious {
	     local $SIG{INT} = 'IGNORE';
	     &more_functions;
	 }
	 sub more_functions {
	     # interrupts still	ignored, for now...
	 }

     Sending a signal to a negative process ID means that you send the signal
     to	the entire Unix	process-group.	This code sends	a hang-up signal to
     all processes in the current process group	(and sets $SIG{HUP} to IGNORE
     so	it doesn't kill	itself):

	 {
	     local $SIG{HUP} = 'IGNORE';
	     kill HUP => -$$;
	     # snazzy writing of: kill('HUP', -$$)
	 }

     Another interesting signal	to send	is signal number zero.	This doesn't
     actually affect another process, but instead checks whether it's alive or
     has changed its UID.

	 unless	(kill 0	=> $kid_pid) {
	     warn "something wicked happened to	$kid_pid";
	 }

     You might also want to employ anonymous functions for simple signal
     handlers:

	 $SIG{INT} = sub { die "\nOutta	here!\n" };

     But that will be problematic for the more complicated handlers that need
     to	reinstall themselves.  Because Perl's signal mechanism is currently
     based on the signal(3) function from the C	library, you may sometimes be
     so	misfortunate as	to run on systems where	that function is "broken",
     that is, it behaves in the	old unreliable SysV way	rather than the	newer,
     more reasonable BSD and POSIX fashion.  So	you'll see defensive people
     writing signal handlers like this:



									Page 2






PERLIPC(1)							    PERLIPC(1)



	 sub REAPER {
	     $waitedpid	= wait;
	     # loathe sysV: it makes us	not only reinstate
	     # the handler, but	place it after the wait
	     $SIG{CHLD}	= \&REAPER;
	 }
	 $SIG{CHLD} = \&REAPER;
	 # now do something that forks...

     or	even the more elaborate:

	 use POSIX ":sys_wait_h";
	 sub REAPER {
	     my	$child;
	     while ($child = waitpid(-1,WNOHANG)) {
		 $Kid_Status{$child} = $?;
	     }
	     $SIG{CHLD}	= \&REAPER;  # still loathe sysV
	 }
	 $SIG{CHLD} = \&REAPER;
	 # do something	that forks...

     Signal handling is	also used for timeouts in Unix,	  While	safely
     protected within an eval{}	block, you set a signal	handler	to trap	alarm
     signals and then schedule to have one delivered to	you in some number of
     seconds.  Then try	your blocking operation, clearing the alarm when it's
     done but not before you've	exited your eval{} block.  If it goes off,
     you'll use	die() to jump out of the block,	much as	you might using
     longjmp() or throw() in other languages.

     Here's an example:

	 eval {
	     local $SIG{ALRM} =	sub { die "alarm clock restart"	};
	     alarm 10;
	     flock(FH, 2);   # blocking	write lock
	     alarm 0;
	 };
	 if ($@	and $@ !~ /alarm clock restart/) { die }

     For more complex signal handling, you might see the standard POSIX
     module.  Lamentably, this is almost entirely undocumented,	but the
     t/lib/posix.t file	from the Perl source distribution has some examples in
     it.

Named Pipes    [Toc]    [Back]

     A named pipe (often referred to as	a FIFO)	is an old Unix IPC mechanism
     for processes communicating on the	same machine.  It works	just like a
     regular, connected	anonymous pipes, except	that the processes rendezvous
     using a filename and don't	have to	be related.





									Page 3






PERLIPC(1)							    PERLIPC(1)



     To	create a named pipe, use the Unix command mknod(1) or on some systems,
     mkfifo(1).	 These may not be in your normal path.

	 # system return val is	backwards, so && not ||
	 #
	 $ENV{PATH} .= ":/etc:/usr/etc";
	 if  (	    system('mknod',  $path, 'p')
		 && system('mkfifo', $path) )
	 {
	     die "mk{nod,fifo} $path failed;
	 }

     A fifo is convenient when you want	to connect a process to	an unrelated
     one.  When	you open a fifo, the program will block	until there's
     something on the other end.

     For example, let's	say you'd like to have your .signature file be a named
     pipe that has a Perl program on the other end.  Now every time any
     program (like a mailer, news reader, finger program, etc.)	tries to read
     from that file, the reading program will block and	your program will
     supply the	new signature.	We'll use the pipe-checking file test -p to
     find out whether anyone (or anything) has accidentally removed our	fifo.

	 chdir;	# go home
	 $FIFO = '.signature';
	 $ENV{PATH} .= ":/etc:/usr/games";

	 while (1) {
	     unless (-p	$FIFO) {
		 unlink	$FIFO;
		 system('mknod', $FIFO,	'p')
		     &&	die "can't mknod $FIFO:	$!";
	     }

	     # next line blocks	until there's a	reader
	     open (FIFO, "> $FIFO") || die "can't write	$FIFO: $!";
	     print FIFO	"John Smith (smith\@host.org)\n", `fortune -s`;
	     close FIFO;
	     sleep 2;	 # to avoid dup	signals
	 }


Using open() for IPC
     Perl's basic open() statement can also be used for	unidirectional
     interprocess communication	by either appending or prepending a pipe
     symbol to the second argument to open().  Here's how to start something
     up	in a child process you intend to write to:








									Page 4






PERLIPC(1)							    PERLIPC(1)



	 open(SPOOLER, "| cat -v | lpr -h 2>/dev/null")
			 || die	"can't fork: $!";
	 local $SIG{PIPE} = sub	{ die "spooler pipe broke" };
	 print SPOOLER "stuff\n";
	 close SPOOLER || die "bad spool: $! $?";

     And here's	how to start up	a child	process	you intend to read from:

	 open(STATUS, "netstat -an 2>&1	|")
			 || die	"can't fork: $!";
	 while (<STATUS>) {
	     next if /^(tcp|udp)/;
	     print;
	 }
	 close STATUS || die "bad netstat: $! $?";

     If	one can	be sure	that a particular program is a Perl script that	is
     expecting filenames in @ARGV, the clever programmer can write something
     like this:

	 $ program f1 "cmd1|" -	f2 "cmd2|" f3 <	tmpfile

     and irrespective of which shell it's called from, the Perl	program	will
     read from the file	f1, the	process	cmd1, standard input (tmpfile in this
     case), the	f2 file, the cmd2 command, and finally the f3 file.  Pretty
     nifty, eh?

     You might notice that you could use backticks for much the	same effect as
     opening a pipe for	reading:

	 print grep { !/^(tcp|udp)/ } `netstat -an 2>&1`;
	 die "bad netstat" if $?;

     While this	is true	on the surface,	it's much more efficient to process
     the file one line or record at a time because then	you don't have to read
     the whole thing into memory at once. It also gives	you finer control of
     the whole process,	letting	you to kill off	the child process early	if
     you'd like.

     Be	careful	to check both the open() and the close() return	values.	 If
     you're writing to a pipe, you should also trap SIGPIPE.  Otherwise, think
     of	what happens when you start up a pipe to a command that	doesn't	exist:
     the open()	will in	all likelihood succeed (it only	reflects the fork()'s
     success), but then	your output will fail--spectacularly.  Perl can't know
     whether the command worked	because	your command is	actually running in a
     separate process whose exec() might have failed.  Therefore, while
     readers of	bogus commands return just a quick end of file,	writers	to
     bogus command will	trigger	a signal they'd	better be prepared to handle.
     Consider:






									Page 5






PERLIPC(1)							    PERLIPC(1)



	 open(FH, "|bogus");
	 print FH "bang\n";
	 close FH;


     Filehandles    [Toc]    [Back]

     Both the main process and the child process share the same	STDIN, STDOUT
     and STDERR	filehandles.  If both processes	try to access them at once,
     strange things can	happen.	 You may want to close or reopen the
     filehandles for the child.	 You can get around this by opening your pipe
     with open(), but on some systems this means that the child	process	cannot
     outlive the parent.

     Background	Processes

     You can run a command in the background with:

	 system("cmd &");

     The command's STDOUT and STDERR (and possibly STDIN, depending on your
     shell) will be the	same as	the parent's.  You won't need to catch SIGCHLD
     because of	the double-fork	taking place (see below	for more details).

     Complete Dissociation of Child from Parent    [Toc]    [Back]

     In	some cases (starting server processes, for instance) you'll want to
     complete dissociate the child process from	the parent.  The following
     process is	reported to work on most Unixish systems.  Non-Unix users
     should check their	Your_OS::Process module	for other solutions.

     o	 Open /dev/tty and use the TIOCNOTTY ioctl on it.  See the tty(4)
	 manpage for details.

     o	 Change	directory to /

     o	 Reopen	STDIN, STDOUT, and STDERR so they're not connected to the old
	 tty.

     o	 Background yourself like this:

	     fork && exit;


     Safe Pipe Opens    [Toc]    [Back]

     Another interesting approach to IPC is making your	single program go
     multiprocess and communicate between (or even amongst) yourselves.	 The
     open() function will accept a file	argument of either "-|"	or "|-"	to do
     a very interesting	thing: it forks	a child	connected to the filehandle
     you've opened.  The child is running the same program as the parent.
     This is useful for	safely opening a file when running under an assumed



									Page 6






PERLIPC(1)							    PERLIPC(1)



     UID or GID, for example.  If you open a pipe to minus, you	can write to
     the filehandle you	opened and your	kid will find it in his	STDIN.	If you
     open a pipe from minus, you can read from the filehandle you opened
     whatever your kid writes to his STDOUT.

	 use English;
	 my $sleep_count = 0;

	 do {
	     $pid = open(KID_TO_WRITE, "|-");
	     unless (defined $pid) {
		 warn "cannot fork: $!";
		 die "bailing out" if $sleep_count++ > 6;
		 sleep 10;
	     }
	 } until defined $pid;

	 if ($pid) {  #	parent
	     print KID_TO_WRITE	@some_data;
	     close(KID_TO_WRITE) || warn "kid exited $?";
	 } else	{     #	child
	     ($EUID, $EGID) = ($UID, $GID); # suid progs only
	     open (FILE, "> /safe/file")
		 || die	"can't open /safe/file:	$!";
	     while (<STDIN>) {
		 print FILE; # child's STDIN is	parent's KID
	     }
	     exit;  # don't forget this
	 }

     Another common use	for this construct is when you need to execute
     something without the shell's interference.  With system(), it's
     straightforward, but you can't use	a pipe open or backticks safely.
     That's because there's no way to stop the shell from getting its hands on
     your arguments.   Instead,	use lower-level	control	to call	exec()
     directly.

     Here's a safe backtick or pipe open for read:

	 # add error processing	as above
	 $pid =	open(KID_TO_READ, "-|");

	 if ($pid) {   # parent
	     while (<KID_TO_READ>) {
		 # do something	interesting
	     }
	     close(KID_TO_READ)	|| warn	"kid exited $?";








									Page 7






PERLIPC(1)							    PERLIPC(1)



	 } else	{      # child
	     ($EUID, $EGID) = ($UID, $GID); # suid only
	     exec($program, @options, @args)
		 || die	"can't exec program: $!";
	     # NOTREACHED
	 }

     And here's	a safe pipe open for writing:

	 # add error processing	as above
	 $pid =	open(KID_TO_WRITE, "|-");
	 $SIG{ALRM} = sub { die	"whoops, $program pipe broke" };

	 if ($pid) {  #	parent
	     for (@data) {
		 print KID_TO_WRITE;
	     }
	     close(KID_TO_WRITE) || warn "kid exited $?";

	 } else	{     #	child
	     ($EUID, $EGID) = ($UID, $GID);
	     exec($program, @options, @args)
		 || die	"can't exec program: $!";
	     # NOTREACHED
	 }

     Note that these operations	are full Unix forks, which means they may not
     be	correctly implemented on alien systems.	 Additionally, these are not
     true multithreading.  If you'd like to learn more about threading,	see
     the modules file mentioned	below in the SEE ALSO section.

     Bidirectional Communication with Another Process    [Toc]    [Back]

     While this	works reasonably well for unidirectional communication,	what
     about bidirectional communication?	 The obvious thing you'd like to do
     doesn't actually work:

	 open(PROG_FOR_READING_AND_WRITING, "| some program |")

     and if you	forget to use the -w flag, then	you'll miss out	entirely on
     the diagnostic message:

	 Can't do bidirectional	pipe at	-e line	1.

     If	you really want	to, you	can use	the standard open2() library function
     to	catch both ends.  There's also an open3() for tridirectional I/O so
     you can also catch	your child's STDERR, but doing so would	then require
     an	awkward	select() loop and wouldn't allow you to	use normal Perl	input
     operations.






									Page 8






PERLIPC(1)							    PERLIPC(1)



     If	you look at its	source,	you'll see that	open2()	uses low-level
     primitives	like Unix pipe() and exec() to create all the connections.
     While it might have been slightly more efficient by using socketpair(),
     it	would have then	been even less portable	than it	already	is.  The
     open2() and open3() functions are	unlikely to work anywhere except on a
     Unix system or some other one purporting to be POSIX compliant.

     Here's an example of using	open2():

	 use FileHandle;
	 use IPC::Open2;
	 $pid =	open2( \*Reader, \*Writer, "cat	-u -n" );
	 Writer->autoflush(); #	default	here, actually
	 print Writer "stuff\n";
	 $got =	<Reader>;

     The problem with this is that Unix	buffering is really going to ruin your
     day.  Even	though your Writer filehandle is auto-flushed, and the process
     on	the other end will get your data in a timely manner, you can't usually
     do	anything to force it to	give it	back to	you in a similarly quick
     fashion.  In this case, we	could, because we gave cat a -u	flag to	make
     it	unbuffered.  But very few Unix commands	are designed to	operate	over
     pipes, so this seldom works unless	you yourself wrote the program on the
     other end of the double-ended pipe.

     A solution	to this	is the nonstandard Comm.pl library.  It	uses pseudottys
 to make your program behave more reasonably:

	 require 'Comm.pl';
	 $ph = open_proc('cat -n');
	 for (1..10) {
	     print $ph "a line\n";
	     print "got	back ",	scalar <$ph>;
	 }

     This way you don't	have to	have control over the source code of the
     program you're using.  The	Comm library also has expect() and interact()
     functions.	 Find the library (and we hope its successor IPC::Chat)	at
     your nearest CPAN archive as detailed in the SEE ALSO section below.

Sockets: Client/Server Communication
     While not limited to Unix-derived operating systems (e.g.,	WinSock	on PCs
     provides socket support, as do some VMS libraries), you may not have
     sockets on	your system, in	which case this	section	probably isn't going
     to	do you much good.  With	sockets, you can do both virtual circuits
     (i.e., TCP	streams) and datagrams (i.e., UDP packets).  You may be	able
     to	do even	more depending on your system.

     The Perl function calls for dealing with sockets have the same names as
     the corresponding system calls in C, but their arguments tend to differ
     for two reasons: first, Perl filehandles work differently than C file
     descriptors.  Second, Perl	already	knows the length of its	strings, so



									Page 9






PERLIPC(1)							    PERLIPC(1)



     you don't need to pass that information.

     One of the	major problems with old	socket code in Perl was	that it	used
     hard-coded	values for some	of the constants, which	severely hurt
     portability.  If you ever see code	that does anything like	explicitly
     setting $AF_INET =	2, you know you're in for big trouble:	An
     immeasurably superior approach is to use the Socket module, which more
     reliably grants access to various constants and functions you'll need.

     If	you're not writing a server/client for an existing protocol like NNTP
     or	SMTP, you should give some thought to how your server will know	when
     the client	has finished talking, and vice-versa.  Most protocols are
     based on one-line messages	and responses (so one party knows the other
     has finished when a "\n" is received) or multi-line messages and
     responses that end	with a period on an empty line ("\n.\n"	terminates a
     message/response).

     Internet TCP Clients and Servers    [Toc]    [Back]

     Use Internet-domain sockets when you want to do client-server
     communication that	might extend to	machines outside of your own system.

     Here's a sample TCP client	using Internet-domain sockets:

	 #!/usr/bin/perl -w
	 require 5.002;
	 use strict;
	 use Socket;
	 my ($remote,$port, $iaddr, $paddr, $proto, $line);

	 $remote  = shift || 'localhost';
	 $port	  = shift || 2345;  # random port
	 if ($port =~ /\D/) { $port = getservbyname($port, 'tcp') }
	 die "No port" unless $port;
	 $iaddr	  = inet_aton($remote)		     ||	die "no	host: $remote";
	 $paddr	  = sockaddr_in($port, $iaddr);

	 $proto	  = getprotobyname('tcp');
	 socket(SOCK, PF_INET, SOCK_STREAM, $proto)  ||	die "socket: $!";
	 connect(SOCK, $paddr)	  || die "connect: $!";
	 while (defined($line =	<SOCK>)) {
	     print $line;
	 }

	 close (SOCK)		 || die	"close:	$!";
	 exit;

     And here's	a corresponding	server to go along with	it.  We'll leave the
     address as	INADDR_ANY so that the kernel can choose the appropriate
     interface on multihomed hosts.  If	you want sit on	a particular interface
     (like the external	side of	a gateway or firewall machine),	you should
     fill this in with your real address instead.



								       Page 10






PERLIPC(1)							    PERLIPC(1)



	 #!/usr/bin/perl -Tw
	 require 5.002;
	 use strict;
	 BEGIN { $ENV{PATH} = '/usr/ucb:/bin' }
	 use Socket;
	 use Carp;

	 sub logmsg { print "$0	$$: @_ at ", scalar localtime, "\n" }

	 my $port = shift || 2345;
	 my $proto = getprotobyname('tcp');
	 $port = $1 if $port =~	/(\d+)/; # untaint port	number

	 socket(Server,	PF_INET, SOCK_STREAM, $proto)	     ||	die "socket: $!";
	 setsockopt(Server, SOL_SOCKET,	SO_REUSEADDR,
					     pack("l", 1))   ||	die "setsockopt: $!";
	 bind(Server, sockaddr_in($port, INADDR_ANY))	     ||	die "bind: $!";
	 listen(Server,SOMAXCONN)			     ||	die "listen: $!";

	 logmsg	"server	started	on port	$port";

	 my $paddr;

	 $SIG{CHLD} = \&REAPER;

	 for ( ; $paddr	= accept(Client,Server); close Client) {
	     my($port,$iaddr) =	sockaddr_in($paddr);
	     my	$name =	gethostbyaddr($iaddr,AF_INET);

	     logmsg "connection	from $name [",
		     inet_ntoa($iaddr),	"]
		     at	port $port";

	     print Client "Hello there,	$name, it's now	",
			     scalar localtime, "\n";
	 }

     And here's	a multithreaded	version.  It's multithreaded in	that like most
     typical servers, it spawns	(forks)	a slave	server to handle the client
     request so	that the master	server can quickly go back to service a	new
     client.

	 #!/usr/bin/perl -Tw
	 require 5.002;
	 use strict;
	 BEGIN { $ENV{PATH} = '/usr/ucb:/bin' }
	 use Socket;
	 use Carp;

	 sub spawn;  # forward declaration
	 sub logmsg { print "$0	$$: @_ at ", scalar localtime, "\n" }




								       Page 11






PERLIPC(1)							    PERLIPC(1)



	 my $port = shift || 2345;
	 my $proto = getprotobyname('tcp');
	 $port = $1 if $port =~	/(\d+)/; # untaint port	number

	 socket(Server,	PF_INET, SOCK_STREAM, $proto)	     ||	die "socket: $!";
	 setsockopt(Server, SOL_SOCKET,	SO_REUSEADDR,
					     pack("l", 1))   ||	die "setsockopt: $!";
	 bind(Server, sockaddr_in($port, INADDR_ANY))	     ||	die "bind: $!";
	 listen(Server,SOMAXCONN)			     ||	die "listen: $!";

	 logmsg	"server	started	on port	$port";

	 my $waitedpid = 0;
	 my $paddr;

	 sub REAPER {
	     $waitedpid	= wait;
	     $SIG{CHLD}	= \&REAPER;  # loathe sysV
	     logmsg "reaped $waitedpid"	. ($? ?	" with exit $?"	: '');
	 }

	 $SIG{CHLD} = \&REAPER;

	 for ( $waitedpid = 0;
	       ($paddr = accept(Client,Server))	|| $waitedpid;
	       $waitedpid = 0, close Client)
	 {
	     next if $waitedpid	and not	$paddr;
	     my($port,$iaddr) =	sockaddr_in($paddr);
	     my	$name =	gethostbyaddr($iaddr,AF_INET);

	     logmsg "connection	from $name [",
		     inet_ntoa($iaddr),	"]
		     at	port $port";

	     spawn sub {
		 print "Hello there, $name, it's now ",	scalar localtime, "\n";
		 exec '/usr/games/fortune'
		     or	confess	"can't exec fortune: $!";
	     };

	 }

	 sub spawn {
	     my	$coderef = shift;

	     unless (@_	== 0 &&	$coderef && ref($coderef) eq 'CODE') {
		 confess "usage: spawn CODEREF";
	     }






								       Page 12






PERLIPC(1)							    PERLIPC(1)



	     my	$pid;
	     if	(!defined($pid = fork))	{
		 logmsg	"cannot	fork: $!";
		 return;
	     } elsif ($pid) {
		 logmsg	"begat $pid";
		 return; # I'm the parent
	     }
	     # else I'm	the child -- go	spawn

	     open(STDIN,  "<&Client")	|| die "can't dup client to stdin";
	     open(STDOUT, ">&Client")	|| die "can't dup client to stdout";
	     ##	open(STDERR, ">&STDOUT") || die	"can't dup stdout to stderr";
	     exit &$coderef();
	 }

     This server takes the trouble to clone off	a child	version	via fork() for
     each incoming request.  That way it can handle many requests at once,
     which you might not always	want.  Even if you don't fork(), the listen()
     will allow	that many pending connections.	Forking	servers	have to	be
     particularly careful about	cleaning up their dead children	(called
     "zombies" in Unix parlance), because otherwise you'll quickly fill	up
     your process table.

     We	suggest	that you use the -T flag to use	taint checking (see the
     perlsec manpage) even if we aren't	running	setuid or setgid.  This	is
     always a good idea	for servers and	other programs run on behalf of
     someone else (like	CGI scripts), because it lessens the chances that
     people from the outside will be able to compromise	your system.

     Let's look	at another TCP client.	This one connects to the TCP "time"
     service on	a number of different machines and shows how far their clocks
     differ from the system on which it's being	run:

	 #!/usr/bin/perl  -w
	 require 5.002;
	 use strict;
	 use Socket;

	 my $SECS_of_70_YEARS =	2208988800;
	 sub ctime { scalar localtime(shift) }

	 my $iaddr = gethostbyname('localhost');
	 my $proto = getprotobyname('tcp');
	 my $port = getservbyname('time', 'tcp');
	 my $paddr = sockaddr_in(0, $iaddr);
	 my($host);

	 $| = 1;
	 printf	"%-24s %8s %s\n",  "localhost",	0, ctime(time());





								       Page 13






PERLIPC(1)							    PERLIPC(1)



	 foreach $host (@ARGV) {
	     printf "%-24s ", $host;
	     my	$hisiaddr = inet_aton($host)	 || die	"unknown host";
	     my	$hispaddr = sockaddr_in($port, $hisiaddr);
	     socket(SOCKET, PF_INET, SOCK_STREAM, $proto)   || die "socket: $!";
	     connect(SOCKET, $hispaddr)		 || die	"bind: $!";
	     my	$rtime = '    ';
	     read(SOCKET, $rtime, 4);
	     close(SOCKET);
	     my	$histime = unpack("N", $rtime) - $SECS_of_70_YEARS ;
	     printf "%8d %s\n",	$histime - time, ctime($histime);
	 }


     Unix-Domain TCP Clients and Servers    [Toc]    [Back]

     That's fine for Internet-domain clients and servers, but what about local
     communications?  While you	can use	the same setup,	sometimes you don't
     want to.  Unix-domain sockets are local to	the current host, and are
     often used	internally to implement	pipes.	Unlike Internet	domain
     sockets, Unix domain sockets can show up in the file system with an ls(1)
     listing.

	 $ ls -l /dev/log
	 srw-rw-rw-  1 root	       0 Oct 31	07:23 /dev/log

     You can test for these with Perl's	-S file	test:

	 unless	( -S '/dev/log'	) {
	     die "something's wicked with the print system";
	 }

     Here's a sample Unix-domain client:

	 #!/usr/bin/perl -w
	 require 5.002;
	 use Socket;
	 use strict;
	 my ($rendezvous, $line);

	 $rendezvous = shift ||	'/tmp/catsock';
	 socket(SOCK, PF_UNIX, SOCK_STREAM, 0)	     ||	die "socket: $!";
	 connect(SOCK, sockaddr_un($rendezvous))     ||	die "connect: $!";
	 while (defined($line =	<SOCK>)) {
	     print $line;
	 }
	 exit;

     And here's	a corresponding	server.






								       Page 14






PERLIPC(1)							    PERLIPC(1)



	 #!/usr/bin/perl -Tw
	 require 5.002;
	 use strict;
	 use Socket;
	 use Carp;

	 BEGIN { $ENV{PATH} = '/usr/ucb:/bin' }

	 my $NAME = '/tmp/catsock';
	 my $uaddr = sockaddr_un($NAME);
	 my $proto = getprotobyname('tcp');

	 socket(Server,PF_UNIX,SOCK_STREAM,0)	     ||	die "socket: $!";
	 unlink($NAME);
	 bind  (Server,	$uaddr)			     ||	die "bind: $!";
	 listen(Server,SOMAXCONN)		     ||	die "listen: $!";

	 logmsg	"server	started	on $NAME";

	 $SIG{CHLD} = \&REAPER;

	 for ( $waitedpid = 0;
	       accept(Client,Server) ||	$waitedpid;
	       $waitedpid = 0, close Client)
	 {
	     next if $waitedpid;
	     logmsg "connection	on $NAME";
	     spawn sub {
		 print "Hello there, it's now ", scalar	localtime, "\n";
		 exec '/usr/games/fortune' or die "can't exec fortune: $!";
	     };
	 }

     As	you see, it's remarkably similar to the	Internet domain	TCP server, so
     much so, in fact, that we've omitted several duplicate functions--
     spawn(), logmsg(),	ctime(), and REAPER()--which are exactly the same as
     in	the other server.

     So	why would you ever want	to use a Unix domain socket instead of a
     simpler named pipe?  Because a named pipe doesn't give you	sessions.  You
     can't tell	one process's data from	another's.  With socket	programming,
     you get a separate	session	for each client: that's	why accept() takes two
     arguments.

     For example, let's	say that you have a long running database server
     daemon that you want folks	from the World Wide Web	to be able to access,
     but only if they go through a CGI interface.  You'd have a	small, simple
     CGI program that does whatever checks and logging you feel	like, and then
     acts as a Unix-domain client and connects to your private server.






								       Page 15






PERLIPC(1)							    PERLIPC(1)



TCP Clients with IO::Socket
     For those preferring a higher-level interface to socket programming, the
     IO::Socket	module provides	an object-oriented approach.  IO::Socket is
     included as part of the standard Perl distribution	as of the 5.004
     release.  If you're running an earlier version of Perl, just fetch
     IO::Socket	from CPAN, where you'll	also find find modules providing easy
     interfaces	to the following systems: DNS, FTP, Ident (RFC 931), NIS and
     NISPlus, NNTP, Ping, POP3,	SMTP, SNMP, SSLeay, Telnet, and	Time--just to
     name a few.

     A Simple Client    [Toc]    [Back]

     Here's a client that creates a TCP	connection to the "daytime" service at
     port 13 of	the host name "localhost" and prints out everything that the
     server there cares	to provide.

	 #!/usr/bin/perl -w
	 use IO::Socket;
	 $remote = IO::Socket::INET->new(
			     Proto    => "tcp",
			     PeerAddr => "localhost",
			     PeerPort => "daytime(13)",
			 )
		       or die "cannot connect to daytime port at localhost";
	 while ( <$remote> ) { print }

     When you run this program,	you should get something back that looks like
     this:

	 Wed May 14 08:40:46 MDT 1997

     Here are what those parameters to the new constructor mean:

     Proto
	  This is which	protocol to use.  In this case,	the socket handle
	  returned will	be connected to	a TCP socket, because we want a
	  stream-oriented connection, that is, one that	acts pretty much like
	  a plain old file.  Not all sockets are this of this type.  For
	  example, the UDP protocol can	be used	to make	a datagram socket,
	  used for message-passing.

     PeerAddr
	  This is the name or Internet address of the remote host the server
	  is running on.  We could have	specified a longer name	like
	  "www.perl.com", or an	address	like "204.148.40.9".  For
	  demonstration	purposes, we've	used the special hostname "localhost",
	  which	should always mean the current machine you're running on.  The
	  corresponding	Internet address for localhost is "127.1", if you'd
	  rather use that.






								       Page 16






PERLIPC(1)							    PERLIPC(1)



     PeerPort
	  This is the service name or port number we'd like to connect to.  We
	  could	have gotten away with using just "daytime" on systems with a
	  well-configured system services file,[FOOTNOTE: The system services
	  file is in /etc/services under Unix] but just	in case, we've
	  specified the	port number (13) in parentheses.  Using	just the
	  number would also have worked, but constant numbers make careful
	  programmers nervous.

     Notice how	the return value from the new constructor is used as a
     filehandle	in the while loop?  That's what's called an indirect
     filehandle, a scalar variable containing a	filehandle.  You can use it
     the same way you would a normal filehandle.  For example, you can read
     one line from it this way:

	 $line = <$handle>;

     all remaining lines from is this way:

	 @lines	= <$handle>;

     and send a	line of	data to	it this	way:

	 print $handle "some data\n";


     A Webget Client    [Toc]    [Back]

     Here's a simple client that takes a remote	host to	fetch a	document from,
     and then a	list of	documents to get from that host.  This is a more
     interesting client	than the previous one because it first sends something
     to	the server before fetching the server's	response.

	 #!/usr/bin/perl -w
	 use IO::Socket;
	 unless	(@ARGV > 1) { die "usage: $0 host document ..."	}
	 $host = shift(@ARGV);
	 foreach $document ( @ARGV ) {
	     $remote = IO::Socket::INET->new( Proto	=> "tcp",
					      PeerAddr	=> $host,
					      PeerPort	=> "http(80)",
					     );
	     unless ($remote) {	die "cannot connect to http daemon on $host" }
	     $remote->autoflush(1);
	     print $remote "GET	$document HTTP/1.0\n\n";
	     while ( <$remote> ) { print }
	     close $remote;
	 }

     The web server handing the	"http" service,	which is assumed to be at its
     standard port, number 80.	If your	the web	server you're trying to
     connect to	is at a	different port (like 1080 or 8080), you	should specify



								       Page 17






PERLIPC(1)							    PERLIPC(1)



     as	the named-parameter pair, PeerPort => 8080.  The autoflush method is
     used on the socket	because	otherwise the system would buffer up the
     output we sent it.	 (If you're on a Mac, you'll also need to change every
     "\n" in your code that sends data over the	network	to be a	"\015\012"
     instead.)

     Connecting	to the server is only the first	part of	the process: once you
     have the connection, you have to use the server's language.  Each server
     on	the network has	its own	little command language	that it	expects	as
     input.  The string	that we	send to	the server starting with "GET" is in
     HTTP syntax.  In this case, we simply request each	specified document.
     Yes, we really are	making a new connection	for each document, even	though
     it's the same host.  That's the way you always used to have to speak
     HTTP.  Recent versions of web browsers may	request	that the remote	server
     leave the connection open a little	while, but the server doesn't have to
     honor such	a request.

     Here's an example of running that program,	which we'll call webget:

	 shell_prompt$ webget www.perl.com /guanaco.html
	 HTTP/1.1 404 File Not Found
	 Date: Thu, 08 May 1997	18:02:32 GMT
	 Server: Apache/1.2b6
	 Connection: close
	 Content-type: text/html

	 <HEAD><TITLE>404 File Not Found</TITLE></HEAD>
	 <BODY><H1>File	Not Found</H1>
	 The requested URL /guanaco.html was not found on this server.<P>
	 </BODY>

     Ok, so that's not very interesting, because it didn't find	that
     particular	document.  But a long response wouldn't	have fit on this page.

     For a more	fully-featured version of this program,	you should look	to the
     lwp-request program included with the LWP modules from CPAN.

     Interactive Client	with IO::Socket

     Well, that's all fine if you want to send one command and get one answer,
     but what about setting up something fully interactive, somewhat like the
     way telnet	works?	That way you can type a	line, get the answer, type a
     line, get the answer, etc.

     This client is more complicated than the two we've	done so	far, but if
     you're on a system	that supports the powerful fork	call, the solution
     isn't that	rough.	Once you've made the connection	to whatever service
     you'd like	to chat	with, call fork	to clone your process.	Each of	these
     two identical process has a very simple job to do:	the parent copies
     everything	from the socket	to standard output, while the child
     simultaneously copies everything from standard input to the socket.  To
     accomplish	the same thing using just one process would be much harder,



								       Page 18






PERLIPC(1)							    PERLIPC(1)



     because it's easier to code two processes to do one thing than it is to
     code one process to do two	things.	 (This keep-it-simple principle	is one
     of	the cornerstones of the	Unix philosophy, and good software engineering
     as	well, which is probably	why it's spread	to other systems as well.)

     Here's the	code:

	 #!/usr/bin/perl -w
	 use strict;
	 use IO::Socket;
	 my ($host, $port, $kidpid, $handle, $line);

	 unless	(@ARGV == 2) { die "usage: $0 host port" }
	 ($host, $port)	= @ARGV;

	 # create a tcp	connection to the specified host and port
	 $handle = IO::Socket::INET->new(Proto	   => "tcp",
					 PeerAddr  => $host,
					 PeerPort  => $port)
		or die "can't connect to port $port on $host: $!";

	 $handle->autoflush(1);		     # so output gets there right away
	 print STDERR "[Connected to $host:$port]\n";

	 # split the program into two processes, identical twins
	 die "can't fork: $!" unless defined($kidpid = fork());

	 # the if{} block runs only in the parent process
	 if ($kidpid) {
	     # copy the	socket to standard output
	     while (defined ($line = <$handle>)) {
		 print STDOUT $line;
	     }
	     kill("TERM", $kidpid);		     # send SIGTERM to child
	 }
	 # the else{} block runs only in the child process
	 else {
	     # copy standard input to the socket
	     while (defined ($line = <STDIN>)) {
		 print $handle $line;
	     }
	 }

     The kill function in the parent's if block	is there to send a signal to
     our child process (current	running	in the else block) as soon as the
     remote server has closed its end of the connection.

     The kill at the end of the	parent's block is there	to eliminate the child
     process as	soon as	the server we connect to closes	its end.






								       Page 19






PERLIPC(1)							    PERLIPC(1)



     If	the remote server sends	data a byte at time, and you need that data
     immediately without waiting for a newline (which might not	happen), you
     may wish to replace the while loop	in the parent with the following:

	 my $byte;
	 while (sysread($handle, $byte,	1) == 1) {
	     print STDOUT $byte;
	 }

     Making a system call for each byte	you want to read is not	very efficient
     (to put it	mildly)	but is the simplest to explain and works reasonably
     well.

TCP Servers with IO::Socket
     Setting up	server is little bit more involved than	running	a client.  The
     model is that the server creates a	special	kind of	socket that does
     nothing but listen	on a particular	port for incoming connections.	It
     does this by calling the IO::Socket::INET->new() method with slightly
     different arguments than the client did.

     Proto
	  This is which	protocol to use.  Like our clients, we'll still
	  specify "tcp"	here.

     LocalPort
	  We specify a local port in the LocalPort argument, which we didn't
	  do for the client.  This is service name or port number for which
	  you want to be the server. (Under Unix, ports	under 1024 are
	  restricted to	the superuser.)	 In our	sample,	we'll use port 9000,
	  but you can use any port that's not currently	in use on your system.
	  If you try to	use one	already	in used, you'll	get an "Address
	  already in use" message. Under Unix, the netstat -a command will
	  show which services current have servers.

     Listen
	  The Listen parameter is set to the maximum number of pending
	  connections we can accept until we turn away incoming	clients.
	  Think	of it as a call-waiting	queue for your telephone.  The lowlevel
	Socket module has a special symbol for the system maximum,
	  which	is SOMAXCONN.

     Reuse
	  The Reuse parameter is needed	so that	we restart our server manually
	  without waiting a few	minutes	to allow system	buffers	to clear out.

     Once the generic server socket has	been created using the parameters
     listed above, the server then waits for a new client to connect to	it.
     The server	blocks in the accept method, which eventually an bidirectional
     connection	to the remote client.  (Make sure to autoflush this handle to
     circumvent	buffering.)





								       Page 20






PERLIPC(1)							    PERLIPC(1)



     To	add to user-friendliness, our server prompts the user for commands.
     Most servers don't	do this.  Because of the prompt	without	a newline,
     you'll have to use	the sysread variant of the interactive client above.

     This server accepts one of	five different commands, sending output	back
     to	the client.  Note that unlike most network servers, this one only
     handles one incoming client at a time.  Multithreaded servers are covered
     in	Chapter	6 of the Camel or in the perlipc(1) manpage.

     Here's the	code.  We'll

      #!/usr/bin/perl -w
      use IO::Socket;
      use Net::hostent;		     # for OO version of gethostbyaddr

      $PORT = 9000;		     # pick something not in use

      $server =	IO::Socket::INET->new( Proto	 => 'tcp',
				       LocalPort => $PORT,
				       Listen	 => SOMAXCONN,
				       Reuse	 => 1);

      die "can't setup server" unless $server;
      print "[Server $0	accepting clients]\n";

      while ($client = $server->accept()) {
	$client->autoflush(1);
	print $client "Welcome to $0; type help	for command list.\n";
	$hostinfo = gethostbyaddr($client->peeraddr);
	printf "[Connect from %s]\n", $hostinfo->name || $client->peerhost;
	print $client "Command?	";
	while (	<$client>) {
	  next unless /\S/;	  # blank line
	  if	(/quit|exit/i)	  { last;				      }
	  elsif	(/date|time/i)	  { printf $client "%s\n", scalar localtime;  }
	  elsif	(/who/i	)	  { print  $client `who	2>&1`;		      }
	  elsif	(/cookie/i )	  { print  $client `/usr/games/fortune 2>&1`; }
	  elsif	(/motd/i )	  { print  $client `cat	/etc/motd 2>&1`;      }
	  else {
	    print $client "Commands: quit date who cookie motd\n";
	  }
	} continue {
	   print $client "Command? ";
	}
	close $client;
      }


UDP: Message Passing
     Another kind of client-server setup is one	that uses not connections, but
     messages.	UDP communications involve much	lower overhead but also
     provide less reliability, as there	are no promises	that messages will



								       Page 21






PERLIPC(1)							    PERLIPC(1)



     arrive at all, let	alone in order and unmangled.  Still, UDP offers some
     advantages	over TCP, including being able to "broadcast" or "multicast"
     to	a whole	bunch of destination hosts at once (usually on your local
     subnet).  If you find yourself overly concerned about reliability and
     start building checks into	your message system, then you probably should
     use just TCP to start with.

     Here's a UDP program similar to the sample	Internet TCP client given
     earlier.  However,	instead	of checking one	host at	a time,	the UDP
     version will check	many of	them asynchronously by simulating a multicast
     and then using select() to	do a timed-out wait for	I/O.  To do something
     similar with TCP, you'd have to use a different socket handle for each
     host.

	 #!/usr/bin/perl -w
	 use strict;
	 require 5.002;
	 use Socket;
	 use Sys::Hostname;

	 my ( $count, $hisiaddr, $hispaddr, $histime,
	      $host, $iaddr, $paddr, $port, $proto,
	      $rin, $rout, $rtime, $SECS_of_70_YEARS);

	 $SECS_of_70_YEARS	= 2208988800;

	 $iaddr	= gethostbyname(hostname());
	 $proto	= getprotobyname('udp');
	 $port = getservbyname('time', 'udp');
	 $paddr	= sockaddr_in(0, $iaddr); # 0 means let	kernel pick

	 socket(SOCKET,	PF_INET, SOCK_DGRAM, $proto)   || die "socket: $!";
	 bind(SOCKET, $paddr)			       || die "bind: $!";

	 $| = 1;
	 printf	"%-12s %8s %s\n",  "localhost",	0, scalar localtime time;
	 $count	= 0;
	 for $host (@ARGV) {
	     $count++;
	     $hisiaddr = inet_aton($host)    ||	die "unknown host";
	     $hispaddr = sockaddr_in($port, $hisiaddr);
	     defined(send(SOCKET, 0, 0,	$hispaddr))    || die "send $host: $!";
	 }

	 $rin =	'';
	 vec($rin, fileno(SOCKET), 1) =	1;









								       Page 22






PERLIPC(1)							    PERLIPC(1)



	 # timeout after 10.0 seconds
	 while ($count && select($rout = $rin, undef, undef, 10.0)) {
	     $rtime = '';
	     ($hispaddr	= recv(SOCKET, $rtime, 4, 0))	     ||	die "recv: $!";
	     ($port, $hisiaddr)	= sockaddr_in($hispaddr);
	     $host = gethostbyaddr($hisiaddr, AF_INET);
	     $histime =	unpack("N", $rtime) - $SECS_of_70_YEARS	;
	     printf "%-12s ", $host;
	     printf "%8d %s\n",	$histime - time, scalar	localtime($histime);
	     $count--;
	 }

SysV IPC    [Toc]    [Back]

     While System V IPC	isn't so widely	used as	sockets, it still has some
     interesting uses.	You can't, however, effectively	use SysV IPC or
     Berkeley mmap() to	have shared memory so as to share a variable amongst
     several processes.	 That's	because	Perl would reallocate your string when
     you weren't wanting it to.

     Here's a small example showing shared memory usage.

	 $IPC_PRIVATE =	0;
	 $IPC_RMID = 0;
	 $size = 2000;
	 $key =	shmget($IPC_PRIVATE, $size , 0777 );
	 die unless defined $key;

	 $message = "Message #1";
	 shmwrite($key,	$message, 0, 60	) || die "$!";
	 shmread($key,$buff,0,60) || die "$!";

	 print $buff,"\n";

	 print "deleting $key\n";
	 shmctl($key ,$IPC_RMID, 0) || die "$!";

     Here's an example of a semaphore:

	 $IPC_KEY = 1234;
	 $IPC_RMID = 0;
	 $IPC_CREATE = 0001000;
	 $key =	semget($IPC_KEY, $nsems	, 0666 | $IPC_CREATE );
	 die if	!defined($key);
	 print "$key\n";

     Put this code in a	separate file to be run	in more	than one process.
     Call the file take:

	 # create a semaphore





								       Page 23






PERLIPC(1)							    PERLIPC(1)



	 $IPC_KEY = 1234;
	 $key =	semget($IPC_KEY,  0 , 0	);
	 die if	!defined($key);

	 $semnum = 0;
	 $semflag = 0;

	 # 'take' semaphore
	 # wait	for semaphore to be zero
	 $semop	= 0;
	 $opstring1 = pack("sss", $semnum, $semop, $semflag);

	 # Increment the semaphore count
	 $semop	= 1;
	 $opstring2 = pack("sss", $semnum, $semop,  $semflag);
	 $opstring = $opstring1	. $opstring2;

	 semop($key,$opstring) || die "$!";

     Put this code in a	separate file to be run	in more	than one process.
     Call this file give:

	 # 'give' the semaphore
	 # run this in the original process and	you will see
	 # that	the second process continues

	 $IPC_KEY = 1234;
	 $key =	semget($IPC_KEY, 0, 0);
	 die if	!defined($key);

	 $semnum = 0;
	 $semflag = 0;

	 # Decrement the semaphore count
	 $semop	= -1;
	 $opstring = pack("sss", $semnum, $semop, $semflag);

	 semop($key,$opstring) || die "$!";

     The SysV IPC code above was written long ago, and it's definitely clunky
     looking.  It should at the	very least be made to use strict and require
     "sys/ipc.ph".  Better yet,	check out the IPC::SysV	modules	on CPAN.

NOTES    [Toc]    [Back]

     If	you are	running	under version 5.000 (dubious) or 5.001,	you can	still
     use most of the examples in this document.	 You may have to remove	the
     use strict	and some of the	my() statements	for 5.000, and for both	you'll
     have to load in version 1.2 or older of the Socket.pm module, which is
     included in perl5.002.






								       Page 24






PERLIPC(1)							    PERLIPC(1)



     Most of these routines quietly but	politely return	undef when they	fail
     instead of	causing	your program to	die right then and there due to	an
     uncaught exception.  (Actually, some of the new Socket conversion
     functions	croak()	on bad arguments.)  It is therefore essential that you
     should check the return values of these functions.	 Always	begin your
     socket programs this way for optimal success, and don't forget to add -T
     taint checking flag to the	pound-bang line	for servers:

	 #!/usr/bin/perl -w
	 require 5.002;
	 use strict;
	 use sigtrap;
	 use Socket;

BUGS    [Toc]    [Back]

     All these routines	create system-specific portability problems.  As noted
     elsewhere,	Perl is	at the mercy of	your C libraries for much of its
     system behaviour.	It's probably safest to	assume broken SysV semantics
     for signals and to	stick with simple TCP and UDP socket operations; e.g.,
     don't try to pass open file descriptors over a local UDP datagram socket
     if	you want your code to stand a chance of	being portable.

     Because few vendors provide C libraries that are safely re-entrant, the
     prudent programmer	will do	little else within a handler beyond setting a
     numeric variable that already exists; or, if locked into a	slow
     (restarting) system call, using die() to raise an exception and
     longjmp(3)	out.  In fact, even these may in some cases cause a core dump.
     It's probably best	to avoid signals except	where they are absolutely
     inevitable.  This perilous	problems will be addressed in a	future release
     of	Perl.

AUTHOR    [Toc]    [Back]

     Tom Christiansen, with occasional vestiges	of Larry Wall's	original
     version and suggestions from the Perl Porters.

SEE ALSO    [Toc]    [Back]

      
      
     There's a lot more	to networking than this, but this should get you
     started.

     For intrepid programmers, the classic textbook Unix Network Programming
     by	Richard	Stevens	(published by Addison-Wesley).	Note that most books
     on	networking address networking from the perspective of a	C programmer;
     translation to Perl is left as an exercise	for the	reader.

     The IO::Socke
     manpage describes the low-level interface to sockets.  Besides the
     obvious functions in the perlfunc manpage,	you should also	check out the
     modules file at your nearest CPAN site.  (See the perlmodlib manpage or
     best yet, the Perl	FAQ for	a description of what CPAN is and where	to get
     it.)




								       Page 25






PERLIPC(1)							    PERLIPC(1)



     Section 5 of the modules file is devoted to "Networking, Device Control
     (modems), and Interprocess	Communication",	and contains numerous
     unbundled modules numerous	networking modules, Chat and Expect
     operations, CGI programming, DCE, FTP, IPC, NNTP, Proxy, Ptty, RPC, SNMP,
     SMTP, Telnet, Threads, and	ToolTalk--just to name a few.


								       PPPPaaaaggggeeee 22226666
[ Back ]
 Similar pages
Name OS Title
unix Linux Sockets for local interprocess communication.
mkfifo Linux make FIFOs (named pipes)
ftok Tru64 Generate a standard interprocess communication key
stdipc IRIX standard interprocess communication package
ipc Linux System V interprocess communication mechanisms
pipe NetBSD create descriptor pair for interprocess communication
ipcs HP-UX report status of interprocess communication facilities
pipe OpenBSD create descriptor pair for interprocess communication
pipe FreeBSD create descriptor pair for interprocess communication
ipcs Tru64 Reports Interprocess Communication (IPC) facility status
Copyright © 2004-2005 DeniX Solutions SRL
newsletter delivery service