|
Part 4: Road Testing
by Fred Eady
Start ı Janis
Joplin School of Programming ı Who or What
is Perl? ı Setting Up the Server ı
Applying What Weıve Learned ı Internet
Engine Client Code ı Get on the ıNet
ı Sources and PDF
SETTING UP THE SERVER
Iıve casually mentioned clients, hosts,
and servers so far without going into depth as to who is who. The
good news is that it really doesnıt matter as far as the user goes.
For the programmer, it is self-defining. The server is the host that
runs the Perl program that listens for a TCP/IP connection request.
The client code initiates that request.
This is a simplistic way of looking at
the client/server model. Using Perl, the coding is almost as obvious.
To make good use of Perlıs capabilities in this area, the programmer
must understand the basic building blocks of the Internet. One of
those building blocks is the socket.
A socket is a communications endpoint
that can provide reliable or unreliable communications services. To
a programmer, a socket is a standard structure containing essential
elements needed to communicate with other programs that may or may
not be running on the same host.
Reliable and unreliable sockets are tied
to other Internet building blocks called streams and datagrams,
respectively. Properties of stream-based sockets make
them reliable, bidirectional sequenced communication building
blocks. On the antimatter side of that, datagram-based sockets
lack properties that would guarantee sequenced or reliable data delivery.
When used on top of Internet Protocol (IP), streams are associated
with TCT (Transmission Control Protocol), and datagrams use UDP (User
Datagram Protocol).
In addition to an IP address, the socket
type (stream or datagram) is also dependent on which of the two aforementioned
protocols will be used. One other component, the domain, helps to
define the nature of a socket. A domain can be defined as a Unix or
Internet domain. In Perl, the Internet domain is denoted as PF_INET
and the Unix domain is referenced as PF_UNIX. Iıll only travel in
the Internet domain and my socket types will be designated as SOCK_STREAM
or SOCK_DATAGRAM. To keep complexity to a minimum, I can tell you
now that I wonıt be using UDP in my example, so the SOCK_DATAGRAM
type wonıt be used.
In Perl, the built-in socket and IO::Socket
modules support these socket definitions. The Perl IO::Socket module
is an object-oriented approach to socket programming and is built
on properties of the standard socket module. This approach makes life
easier for the socket programmer because he or she doesnıt have to
twiddle every little bit along the way. The socket programmer can
now call the original socket module functions using the less complicated
IO::Socket module calls. Keeping with the dual domain standard, both
Unix and Internet domains are represented as classes of the IO::Socket
module. The class I will draw from is IO::Socket::INET. As youıve
already guessed, the UNIX domain programmers would use IO::Socket::UNIX.
For those of you who enjoy control, the standard socket module functions
are also supported by Perl and can be used instead of the high-level
IO::Socket function calls. Generally, you have a bit more control
over things if you use the standard socket programming techniques.
If you donıt have to or donıt want to tweak, the IO::Socket methods
will do just fine. Guess which one Iım going to use. Letıs compare
the same server socket formation process performed with the standard
socket calls versus the IO::Socket calls.
There are three major steps in creating
a server socket:
- call the socket function to make the
socket
- bind a name (port number and IP address)
to the socket
- call/listen to wait for a connection
request
Hereıs the standard Perl coding for creating
a stream socket in the Internet domain:
use Socket;
socket(FH,
PF_INET, SOCK_STREAM, getprotobyname(ıtcpı)) || die $!;
The first line indicates that you are
using the library of standard socket services provided with Perl.
The second line is the socket call complete with arguments. The first
argument, FH, is the name of the file handle the socket will be associated
with. The file handle receives requests from clients. Each specific
connection is passed to a different file handle by the accept
function. Iıll cover this process when we get there. You recognize
the second argument as the network domain identifier for the Internet
domain. The domain definition also tells you that IP addresses, not
files, will be used for connections. Recall that SOCK_STREAM tells
you that the socket is of the type stream, which implies TCP/IP will
be the protocol used by the socket. The last argument is actually
a number that represents the protocol type. The function gets the
protocol number represented by "tcp" and passes the number
to the socket function.
The reason for using a function to return
the protocol number instead of just plugging in the right number for
TCP/IP is simple. The numbers change. So, to be sure the right protocol
number is passed, a call is made to retrieve the current protocol
number that is embedded in the library. Creating a socket is a do-or-die
situation. If an error occurs, the socket creation function dies and
sends an error message via $!. $! is the standard error handling device
for Perl. A message and an error number are associated with $!. If
all goes well, thatıs all I should have to say about that.
The next step is to bind the server socket
to a port on the local machine by passing a port and an address data
structure to the bind function via sockaddr_in. The Perl code
for this operation is:
use Socket;
$socket_name = sockaddr_in(80,
INADDR_ANY);
bind (FH, $socket_name)
|| die $!;
Line 1 remains the same here as in the
socket creation example. The second line above allows the system to
pick an appropriate IP address (INADDR_ANY) and designates well-known
Port 80 (HTTP) as the port of choice. FH references the socket I just
created in the preceding code. Again, the bind function is do-or-die
resulting in error messages being generated using the built-in services
of $!.
The final step in the server socket creation
process is to invoke the listen function. Kicking off the listen
function signals the operating system that the server is ready to
accept incoming network connections on the designated port. The listen
function is simple:
listen (FH, $length)
In the listen function arguments,
the socket is again represented by its file handle. To accommodate
multiple clients, a queue length is specified. The queue length is
the number of clients that can wait for an accept at one time.
I promised to discuss the accept
function when the time was right. Well, itıs right. When a client
requests a connection, the accept function makes the connection
and assigns a new file handle specific to that connection. The coding
for the accept function is shown below:
accept (NEW, FH) || die $!;
The new file handle that accept
assigns is represented by NEW in the argument field. The answering
socket file handle, the original server socket, is the last argument
before the do-or-die procedure. At this point, the server can read
and write to the file handle new for its communication with the client.
OK. Now letıs do the same thing with
IO::Socket:
use IO::Socket;
$sock = new IO::Socket::INET
(LocalAddr => ıedtp.comı,
LocalPort => 8080,
Proto => ıtcpı,
Listen => 5);
die "$!" unless
$sock;
$new_sock = $sock->accept();
You already know what the first line
does. The rest of the code short of the do-or-die creates a socket,
binds the socket with an IP address and port number, and invokes the
listen function with a queue length of 5. Everything is in
place and just waiting for a connection request from the client. When
a connection request is received, the accept method is called
and a new socket is created to service the request. In both the socket
and IO::Socket examples, a close must be issued to destroy the socket
structure when communications is complete.
PREVIOUS
NEXT
Circuit Cellar provides up-to-date information for engineers. Visit
www.circuitcellar.com for
more information and additional articles.
For subscription information, call (860) 875-2199, subscribe@circuitcellar.com
or subscribe online.
ıCircuit Cellar, the Magazine for Computer Applications. Posted with
permission. |