You want to write a server that forks a subprocess to handle each new client.
Fork in the accept
loop, and use a $SIG{CHLD}
handler to reap the children.
# set up the socket SERVER, bind and listen ... use POSIX qw(:sys_wait_h); sub REAPER { 1 until (-1 == waitpid(-1, WNOHANG)); $SIG{CHLD} = \&REAPER; # unless $] >= 5.002 } $SIG{CHLD} = \&REAPER; while ($hisaddr = accept(CLIENT, SERVER)) { next if $pid = fork; # parent die "fork: $!" unless defined $pid; # failure # otherwise child close(SERVER); # no use to child # ... do something exit; # child leaves } continue { close(CLIENT); # no use to parent }
This approach is very common for SOCK_STREAM servers in the Internet and Unix domains. Each incoming connection gets a cloned server of its own. The model is:
This technique isn't used with SOCK_DGRAM sockets because their method of communication is different. The time it takes to fork makes the forking model impractical for UDP-style servers. Instead of working with a series of stateful, long-running connections, SOCK_DGRAM servers work with a bunch of sporadic datagrams, usually statelessly. With them, the model must become:
The child process deals with the new connection. Because it will never use the SERVER socket, we immediately close it. This is partly to keep a tidy house, but mainly so that the server socket is closed when the parent (server) process exits. If the children do not close the SERVER socket, the operating system considers the socket still open even when the parent dies. For more on this, see Recipe 17.9.
%SIG
ensures that we clean up after our children when they exit. See Chapter 16, Process Management and Communication for details.
The
fork
and
accept
functions in Chapter 3 of Programming Perl and in perlfunc (1); Recipe 16.15; Recipe 16.19; Recipe 17.12; Recipe 17.13
Copyright © 2002 O'Reilly & Associates. All rights reserved.