use POSIX ":sys_wait_h";
sub REAPER {
my $child;
- while ($child = waitpid(-1,WNOHANG)) {
+ while (($child = waitpid(-1,WNOHANG)) > 0) {
$Kid_Status{$child} = $?;
}
$SIG{CHLD} = \&REAPER; # still loathe sysV
To forbid signal handlers altogether would bars you from
many interesting programs, including virtually everything in this manpage,
-since you could no longer even write SIGCHLD handlers. Their dodginess
-is expected to be addresses in the 5.005 release.
+since you could no longer even write SIGCHLD handlers.
=head1 Using open() for IPC
open(PROG_FOR_READING_AND_WRITING, "| some program |")
-and if you forget to use the B<-w> flag, then you'll miss out
-entirely on the diagnostic message:
+and if you forget to use the C<use warnings> pragma or the B<-w> flag,
+then you'll miss out entirely on the diagnostic message:
Can't do bidirectional pipe at -e line 1.
my $port = shift || 2345;
my $proto = getprotobyname('tcp');
- $port = $1 if $port =~ /(\d+)/; # untaint port number
+
+ ($port) = $port =~ /^(\d+)$/ || die "invalid port";
socket(Server, PF_INET, SOCK_STREAM, $proto) || die "socket: $!";
setsockopt(Server, SOL_SOCKET, SO_REUSEADDR,
my $port = shift || 2345;
my $proto = getprotobyname('tcp');
- $port = $1 if $port =~ /(\d+)/; # untaint port number
+
+ ($port) = $port =~ /^(\d+)$/ || die "invalid port";
socket(Server, PF_INET, SOCK_STREAM, $proto) || die "socket: $!";
setsockopt(Server, SOL_SOCKET, SO_REUSEADDR,
at port $port";
spawn sub {
+ $|=1;
print "Hello there, $name, it's now ", scalar localtime, $EOL;
exec '/usr/games/fortune' # XXX: `wrong' line terminators
or confess "can't exec fortune: $!";
You can test for these with Perl's B<-S> file test:
unless ( -S '/dev/log' ) {
- die "something's wicked with the print system";
+ die "something's wicked with the log system";
}
Here's a sample Unix-domain client:
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
+IO::Socket from CPAN, where you'll also 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.
}
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
+its standard port, number 80. If the web server you're trying to
connect to is at a different port (like 1080 or 8080), you should specify
-as the named-parameter pair, C<PeerPort =E<gt> 8080>. The C<autoflush>
+as the named-parameter pair, C<< PeerPort => 8080 >>. The C<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 C<"\n"> in your code that sends data over the network to
As always, setting up a 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 C<IO::Socket::INET-E<gt>new()> method with
+It does this by calling the C<< IO::Socket::INET->new() >> method with
slightly different arguments than the client did.
=over
into your message system, then you probably should use just TCP to start
with.
+Note that UDP datagrams are I<not> a bytestream and should not be treated
+as such. This makes using I/O mechanisms with internal buffering
+like stdio (i.e. print() and friends) especially cumbersome. Use syswrite(),
+or better send(), like in the example below.
+
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
$count--;
}
+Note that this example does not include any retries and may consequently
+fail to contact a reachable host. The most prominent reason for this
+is congestion of the queues on the sending host if the number of
+list of hosts to contact is sufficiently large.
+
=head1 SysV IPC
While System V IPC isn't so widely used as sockets, it still has some
Here's a small example showing shared memory usage.
- use IPC::SysV qw(IPC_PRIVATE IPC_RMID S_IRWXU S_IRWXG S_IRWXO);
+ use IPC::SysV qw(IPC_PRIVATE IPC_RMID S_IRWXU);
$size = 2000;
- $key = shmget(IPC_PRIVATE, $size, S_IRWXU|S_IRWXG|S_IRWXO) || die "$!";
- print "shm key $key\n";
+ $id = shmget(IPC_PRIVATE, $size, S_IRWXU) || die "$!";
+ print "shm key $id\n";
$message = "Message #1";
- shmwrite($key, $message, 0, 60) || die "$!";
+ shmwrite($id, $message, 0, 60) || die "$!";
print "wrote: '$message'\n";
- shmread($key, $buff, 0, 60) || die "$!";
+ shmread($id, $buff, 0, 60) || die "$!";
print "read : '$buff'\n";
# the buffer of shmread is zero-character end-padded.
print "un" unless $buff eq $message;
print "swell\n";
- print "deleting shm $key\n";
- shmctl($key, IPC_RMID, 0) || die "$!";
+ print "deleting shm $id\n";
+ shmctl($id, IPC_RMID, 0) || die "$!";
Here's an example of a semaphore:
use IPC::SysV qw(IPC_CREAT);
$IPC_KEY = 1234;
- $key = semget($IPC_KEY, 10, 0666 | IPC_CREAT ) || die "$!";
- print "shm key $key\n";
+ $id = semget($IPC_KEY, 10, 0666 | IPC_CREAT ) || die "$!";
+ print "shm key $id\n";
Put this code in a separate file to be run in more than one process.
Call the file F<take>:
# create a semaphore
$IPC_KEY = 1234;
- $key = semget($IPC_KEY, 0 , 0 );
- die if !defined($key);
+ $id = semget($IPC_KEY, 0 , 0 );
+ die if !defined($id);
$semnum = 0;
$semflag = 0;
# 'take' semaphore
# wait for semaphore to be zero
$semop = 0;
- $opstring1 = pack("sss", $semnum, $semop, $semflag);
+ $opstring1 = pack("s!s!s!", $semnum, $semop, $semflag);
# Increment the semaphore count
$semop = 1;
- $opstring2 = pack("sss", $semnum, $semop, $semflag);
+ $opstring2 = pack("s!s!s!", $semnum, $semop, $semflag);
$opstring = $opstring1 . $opstring2;
- semop($key,$opstring) || die "$!";
+ semop($id,$opstring) || die "$!";
Put this code in a separate file to be run in more than one process.
Call this file F<give>:
# that the second process continues
$IPC_KEY = 1234;
- $key = semget($IPC_KEY, 0, 0);
- die if !defined($key);
+ $id = semget($IPC_KEY, 0, 0);
+ die if !defined($id);
$semnum = 0;
$semflag = 0;
# Decrement the semaphore count
$semop = -1;
- $opstring = pack("sss", $semnum, $semop, $semflag);
+ $opstring = pack("s!s!s!", $semnum, $semop, $semflag);
- semop($key,$opstring) || die "$!";
+ semop($id,$opstring) || die "$!";
The SysV IPC code above was written long ago, and it's definitely
clunky looking. For a more modern look, see the IPC::SysV module
which is included with Perl starting from Perl 5.005.
+A small example demonstrating SysV message queues:
+
+ use IPC::SysV qw(IPC_PRIVATE IPC_RMID IPC_CREAT S_IRWXU);
+
+ my $id = msgget(IPC_PRIVATE, IPC_CREAT | S_IRWXU);
+
+ my $sent = "message";
+ my $type = 1234;
+ my $rcvd;
+ my $type_rcvd;
+
+ if (defined $id) {
+ if (msgsnd($id, pack("l! a*", $type_sent, $sent), 0)) {
+ if (msgrcv($id, $rcvd, 60, 0, 0)) {
+ ($type_rcvd, $rcvd) = unpack("l! a*", $rcvd);
+ if ($rcvd eq $sent) {
+ print "okay\n";
+ } else {
+ print "not okay\n";
+ }
+ } else {
+ die "# msgrcv failed\n";
+ }
+ } else {
+ die "# msgsnd failed\n";
+ }
+ msgctl($id, IPC_RMID, 0) || die "# msgctl failed: $!\n";
+ } else {
+ die "# msgget failed\n";
+ }
+
=head1 NOTES
Most of these routines quietly but politely return C<undef> when they