Network Programming with Perl

Using Perl to make network task is easy—here's how.
A Forking Client

If you want to write a client that accepts commands from STDIN and sends them to the server, the easiest solution is to write a client that forks a child. (A solution can be written using select that does not fork, but it is more complicated.) The client's parent process will read the commands from the user through STDIN and print them to the server. The client's child process will then read from the server and print the responses to STDOUT.

Listing 7.

Listing 7, clientfork.pl, is an example of a client that forks.

To fork in Perl, call the cleverly named fork function. It returns undef if the fork fails. If it succeeds, it returns 0 to the child, non-zero (the child's pid) to the parent. In clientfork.pl, an if statement checks the value of $kid, the return value from the fork. If $kid is true (non-zero, the child's pid), parent executes reading from STDIN printing to the server. If $kid is false (zero), the child executes reading from the server printing to STDOUT.

The following is the example session executing the client code in Listing 7, clientfork.pl connecting to the code in Listing 5, server2way.pl:

[james@client networking]$ clientfork.pl
server.onsight.com
NAME
server.onsight.com
DATE
Tue Oct 27 15:42:58 1998
HELP
DEFAULT
HELLO
Hi

When the parent process is finished reading from STDIN, it executes the killfunction to kill the child process. It is very important the parent reap its child so that the child does not outlive the parent and become a zombie.

A Forking Server

Listing 8.

Servers usually don't handle only one client at a time. One approach to a server that can handle more than one client is a server that forks a child process to handle each client connection. Listing 8, serverfork.pl, is an example of a forking server.

One way for the parent process to reap its children is to define a subroutine and assign a reference to that subroutine to $SIG{CHLD}. (The hash %SIG is Perl's way of handling signals.) In this example, a subroutine named REAP is defined and a reference to this subroutine is assigned to $SIG{CHLD}. When the parent receives the CHLD (child terminated) signal, the REAP subroutine will be invoked.

Within the while loop that accepts all the client connections, the server forks. If the fork returns true, the parent is running and it executes the next statement which immediately transfers control to the continue block, performs the housecleaning step of closing the child socket and waits for the next client to connect. If the fork returns undef, then the fork failed, so the server dies. If the fork returns neither true nor undef, then the child is running, so the parent socket is closed and the child reads from the client and processes the client. When the child is finished processing the client, the child exits and is reaped by the parent.

Thread Programming in Perl5.005

Perl version 5.005 supports thread programming. This means a threaded networking program can be created to be either a server or a client.

Listings 9, 10, and 11 are three different versions of a client that logs into several web servers and determines the type of server being used (Apache, Netscape, etc).

Listing 9.

Listing 9, getservertype1.pl, shows a non-forking, non-threaded client. First, an array of hosts is created and initialized to a few web sites. The subroutine doit is defined to receive the web server name as an argument, open a client connection to that server at port 80 (the HTTP port), send the HTTP request and read each line of response. When the line starting Server: is read, it will extract the server name and store it in$1. Then the host name and web server name are printed. This subroutine is called for each host in the array of hosts.

Here is the output of getservertype1.pl:

processing www.ssc.com...
www.ssc.com: Stronghold/2.2 Apache/1.2.5 PHP/FI-2.0b12
processing www.linuxjournal.com...
www.linuxjournal.com: Stronghold/2.2 Apache/1.2.5 PHP/FI-2.0b12
processing www.perl.com...
www.perl.com: Apache/1.2.6 mod_perl/1.11
processing www.perl.org...
www.perl.org: Apache/1.2.5
processing www.nytimes.com...
www.nytimes.com: Netscape-Enterprise/2.01
processing www.onsight.com...
www.onsight.com: Netscape-Communications/1.12
processing www.avue.com...
www.avue.com: Netscape-Communications/1.12

Note that the hosts are processed in the same order as stored in @hosts.

Listing 10.

Listing 10, getservertype2.pl, is a forking version of getservertype1.pl. The forking occurs within the foreach loop. The fork is executed and if it returns true, the parent then executes the next statement to the next host name. If the fork returns undef, then the program dies. Otherwise, the child calls the doit function passing in the host, then exits. After the parent completes its work in the while loop, it waits for all child processes to finish, then exits.

Here is the output of getservertype2.pl:

processing www.ssc.com...
processing www.linuxjournal.com...
processing www.perl.com...
processing www.perl.org...
processing www.nytimes.com...
processing www.onsight.com...
processing www.avue.com...
www.onsight.com: Netscape-Communications/1.12
www.nytimes.com: Netscape-Enterprise/2.01
www.avue.com: Netscape-Communications/1.12
www.linuxjournal.com: Stronghold/2.2 Apache/1.2.5 PHP/FI-2.0b12
www.perl.com: Apache/1.2.6 mod_perl/1.11
www.ssc.com: Stronghold/2.2 Apache/1.2.5 PHP/FI-2.0b12
www.perl.org: Apache/1.2.5
Parent exiting...

Note that the hosts are not printed in the order stored in @hosts. They are printed in the order processed, the slower hosts taking longer than the faster ones.

Listing 11.

Listing 11, getservertype3.pl, is a threaded version. In the loop through the host names, a new Thread object is created. When creating the Thread, the new method is passed a reference to a subroutine that the thread will execute, as well as the arguments passed into that subroutine. The thread then executes its subroutine and when the subroutine returns, the thread is destroyed. Here is the output of getservertype3.pl:

processing www.ssc.com...
processing www.linuxjournal.com...
processing www.perl.com...
processing www.perl.org...
processing www.nytimes.com...
processing www.onsight.com...
processing www.avue.com...
www.nytimes.com: Netscape-Enterprise/2.01
www.onsight.com: Netscape-Communications/1.12
www.avue.com: Netscape-Communications/1.12
www.linuxjournal.com: Stronghold/2.2 Apache/1.2.5 PHP/FI-2.0b12
www.perl.com: Apache/1.2.6 mod_perl/1.11
www.ssc.com: Stronghold/2.2 Apache/1.2.5 PHP/FI-2.0b12
www.perl.org: Apache/1.2.5


+ Recent posts