|
Who is this for This
article is for those who want to learn more about using the
IO::Socket module to allow two programs to communicate with each
other.
Introduction
You should
now know what a client and server program is. Simply put, a client
requests a service and a server services the request. There are
several ways to do this. The crudest will be to call a program within
perl and pass the parameters during the call. Another way is to use
pipes. A program can call another program but the input to the called
program will be passed through the STDIN of the other program. Both
methods are crude and allow only for simple passing of input and
output. Another way to do this is using sockets.
Sockets allow two programs to
communicate with each other. The server binds a port on the machine.
The client connects to that port to communicate with the server
IO:Socket Module Perl
has a module that simplifies socket communication. It is called
IO::Socket. Simply put, the client has to connect to the server
socket. The server meanwhile has to get the port and listen to
anything coming in on that socket.
Server script The server
is the program that listens to a request and processes the request.
For our exercise, we will write a simple server that accepts numbers
and adds all numbers up. (I know, you might as well do this in the
client program but this is just an illustration)
The script has to do the
following:
Open
the listening socket by specifying the protocol, local host address
and the port
Actually
listen to any requests
When
a request is accepted, process the request
Return the result to the
client
Simple!
The code to do this is as follows:
use IO::Socket; ##################################### # Server Script: # Copyright 2003 (c) Philip Yuson # this program is distributed according to # the terms of the Perl license # Use at your own risk ##################################### $local = IO::Socket::INET->new( Proto => 'tcp', # protocol LocalAddr => 'localhost:8081', # Host and port to listen to # Change the port if 8081 is being used Reuse => 1 ) or die "$!"; $local->listen(); # listen $local->autoflush(1); # To send response immediately print "At your service. Waiting...\n"; my $addr; # Client handle while ($addr = $local->accept() ) { # receive a request print "Connected from: ", $addr->peerhost(); # Display messages print " Port: ", $addr->peerport(), "\n"; my $result; # variable for Result while (<$addr>) { # Read all messages from client # (Assume all valid numbers) last if m/^end/gi; # if message is 'end' # then exit loop print "Received: $_"; # Print received message print $addr $_; # Send received message back # to verify $result += $_; # Add value to result } chomp; # Remove the if (m/^end/gi) { # You need this. Otherwise if # the client terminates abruptly # The server will encounter an # error when it sends the result back # and terminate my $send = "result=$result"; # Format result message print $addr "$send\n"; # send the result message print "Result: $send\n"; # Display sent message } print "Closed connection\n"; # Inform that connection # to client is closed close $addr; # close client print "At your service. Waiting...\n"; # Wait again for next request }
|
Save this as server.pl.
Start a command window and run this. The output should show something
like this:
At your
service. Waiting...
This means that the server is
listening to any request on the given port.
Client Script
The client drives the process. It
sends a request to the server. It has to connect to the port the
server is listening to. It should then receive some form of input
from STDIN to send to the server. At the end, it sends an 'end'
message to the server.
To illustrate interactive
communication, the server will echo back anything it receives from
the client. The client then verifies this against what it sent. If it
does not match, then it is an error.
When the client receives and 'end'
from STDIN, it receives the result from the server and prints out the
result.
Ready for the code?
use IO::Socket; ##################################### # Client Script: # Copyright 2003 (c) Philip Yuson # this program is distributed according to # the terms of the Perl license # Use at your own risk ##################################### $remote = IO::Socket::INET->new( Proto => 'tcp', # protocol PeerAddr=> 'localhost', # Address of server PeerPort=> "8081", # port of server Reuse => 1, ) or die "$!"; print "Connected to ", $remote->peerhost, # Info message " on port: ", $remote->peerport, "\n"; $remote->autoflush(1); # Send immediately while (<>) { # Get input from STDIN print $remote $_; # Send to Server last if m/^end/gi; # If 'end' then exit loop my $line = <$remote>; # Receive echo from server if ($line ne $_) { # If not the same as input print "Error in sending output\n"; # error exit; # Terminate } } my $res = <$remote>; # Receive result from server $res =~ m/result=(\d*)/gi; # Get the numeric result from message print "Result: $1\n"; # Print the result print "End of client\n"; # End of client close $remote; # Close socket
|
Save this as client.pl.
Start another command window and run this. Make sure that the
server.pl is running also.
The client should display
something like this:
Connected
to 127.0.0.1 on port: 8081
Type in any set of numbers and
press <Enter>each time. When you are done, type end
and press <enter>. Look at the result. The server should
return the right computation.
Where can you use this? The
server can take the place of say a tax calculation routine where you
send all the relevant numbers and at the end receive the calculated
tax.
The server can also be modified to
perform database access and return the result to the client. The
client can send a message like select tablename. The
server can then format the proper SQL statement to get the rows. With
this method, programmers on the client side need not worry about SQL
statements because the programmers with SQL skills can write the SQL
statements on the server side.
|