Internet socket programming in Perl
Plugged In
Some would make the case that Perl is the most used and most capable scripting language on the Internet today, and this is probably true. Its versatility and ease of use has made it an industry standard used throughout the world.
With Perl sockets, you can communicate with any computer that is connected by the Internet or a network. To communicate with this other computer, you specify the server to connect to and a port to connect through. After the initial connection, you can use that connection just as you would a file handle, with just a few differences that are mainly academic.
To put it simply, the two sides of a Perl socket are the server and the client. It doesn't really matter which is which – the communication process is essentially the same, because the client can send information to the server and vice versa. The communication process is surprisingly simple. The process starts with the creation of the server. The server patiently waits for a connection request from the client, which can be created any time after the creation of the server. The client connects to the server with the address of the server and the mutually agreed upon port number. If the port numbers are different, no connection is made. Once the client is connected, data may be sent from the server to the client, and vice versa.
Data can be sent over a socket two ways: both ways using one socket, or one way using two sockets. In the one-socket method, data is sent from the server to the client and from the client to the server through the same socket. In the two-socket method, one socket is used to send data from the server to the client, and one is used to send data from the client to the server. I'll be touching on both methods in this article, so read on.
Sockets exist on all major operating systems (OSs). They are the accepted way to achieve communication between computers. Keeping this in mind, you can connect a Unix computer to a Windows computer (and vice versa) with little or no trouble – if Perl is successfully installed on both machines. You should note that the ports used for an operation like this differ from OS to OS. Just keep in mind a few simple facts: Ports below 1024 are normally reserved for system use, so save yourself a headache and don't use them. HTTP requests usually use port 80 or 8080. Port numbers roughly in the range 1025 to 5000 usually produce adequate results. Just be sure to use the same port on both computers being connected. Now, on to the practical coding.
Before you can connect to a server, or even create the server, you must know whether you can establish a connection on that port. To do this, use the can_read
or can_write
methods of the IO::Select module, which is included with Perl. The example in Listing 1 checks four sockets to see which are available for the connection. This example uses the can_read
method to check whether any of the sockets can be used. You could just as easily use the can_write
method in this particular example – the end result would be the same.
Listing 1
Checking Port Availability
01 Use IO::Select 02 03 $select = IO::Select->new(); 04 05 $select->add($socket1); 06 $select->add($socket2); 07 $select->add($socket3); 08 $select->add($socket4); 09 10 @ok_to_read = $select->can_read($timeout); 11 12 foreach $socket (@ok_to_read) { 13 $socket->recv($data_buffer, $flags) 14 print $data_buffer; 15 }
The script starts by declaring the IO::Select module for use. A new instance named $select
is created with the new()
method. Four sockets are then created by the add()
method, and the sockets are placed into the @ok_to_read
array, where the can_read
method is invoked. A foreach
loop then prints the results from the can_read
call to the contents of the @ok_to_read
array.
The recv
method sends info through the socket. As with recv
, you can use the send
function to send byte streams through your socket. You can also use the simple print
and angle operators (<
and >
) to send text through the socket: Just be sure to use the newline character (\n
) at the end of each line if you're sending text. The newline character is required to send a text string through the socket; if the newline character is missing, no data is sent.
Now that you know how to check the sockets, you can delve into the creation of the common servers and clients that Perl is able to use. I'll start with the creation of a TCP server and a TCP client with IO::Socket. Because both the server and the client work hand in hand, I'll cover them both at the same time. However, I have to cover a few basics; namely, the parameters that are passed to the new()
method of IO::Socket::INET:
PeerAddr
– The DNS address of the machine you'd like to connect to. The address may be the dotted IP address of the machine or the domain name itself (e.g.,walkthegeek.com
).PeerPort
– The port on the host machine you'd like to connect to. I'll use port 2000 for no particular reason.Proto
– The protocol to be used. The options aretcp
orudp
.Type
– The type of connection you'd like to establish, the options beingSOCK_STREAM
fortcp
data,SOCK_DGRAM
forudp
connections, orSOCK_SEQPACKET
for sequential data packet connections. I'll be usingtcp
and theSOCK_STREAM
connection type.LocalAddr
– The local address to be bound, if there is one. I don't use one in the example here.LocalPort
– The local port number to be used.Listen
– The queue size, which is the maximum number of connections allowed.Timeout
– The timeout value for connections.
All socket communications with IO::Socket use these parameters. I'll use the IO::Socket::INET new()
method to return a scalar that holds an indirect file handle type. As you can see in Listing 2, it really is that easy to make a TCP client with the use of IO::Socket::INET sockets.
Listing 2
Making a Client
01 use IO::Socket 02 03 $socket = IO::Socket::INET->new 04 ( 05 PeerAddr => ' ThisDomain.com', 06 PeerPort => '2000', 07 Proto => 'tcp', 08 Type = 'SOCK_STREAM' 09 ) or die "Could not Open Port.\n";
Now I'll write to the server from the client. The connection coding is the same, so it doesn't need to be repeated. As in the example above, the port used is 2000
, the server is ThisDomain.com
, the protocol is tcp
, and the type is SOCK_STREAM
. The following example sends the Hello there!!
text message to the server to be displayed on the server's console:
print $socket "Hello there!!\n"; close ($socket);
Notice that the newline character has been dutifully used on the end of the print
statement. Because I'm writing text through the socket, it will not be transmitted if the newline is omitted.
That's an example of writing to the server, so next, I'll cover reading from the server. The creation of the socket and the subsequent connection are the same; only the print
statement changes:
$answer = <$socket>; print $answer; close ($socket);
This code pulls the message from the server and displays it on the console of the client. Creating a server is as easy as creating the client. The same connection coding is used, only $socket
is replaced with $server
:
$server = IO::Socket::INET->new ( PeerAddr => ' ThisDomain.com', PeerPort => '2000', Proto => 'tcp', Type = 'SOCK_STREAM' ) or die "Could not Open Port.\n";
The change from the creation of the client to the creation of the server is the coding below the connection snippet – a while
loop. The next example shows the server reading from the client:
while ($client = $server->accept()) { $line = <$client>; print $line; } close ($server);
The while
loop calls the accept()
method, which makes the server wait for a client to connect. The body of the while
loop is executed when the client connects, reading (pulling) any messages from the client.
Now that you know how to read from the client, I'll look at writing to the client. The only thing that changes is the body of the while
loop:
while ($client = $server->accept()) { print "Hello Client !!\n"; } close ($server);
Don't forget the newline character! Remember, omitting it will cause problems. In the examples so far, I've used tcp
for the sockets; however, you could just as easily use udp
. Just substitute udp
for tcp
in the Proto
parameter, and use SOCK_DGRAM
in place of SOCK_STREAM
for the Type
parameter. Simple.
Now you're at the forefront of Internet socket programming. With this knowledge, you can create chat programs, run a multiplayer game over the Internet, and just generally have fun.
Buy this article as PDF
(incl. VAT)