Lead Image © higyou, 123RF.com

Lead Image © higyou, 123RF.com

Internet socket programming in Perl

Plugged In

Article from ADMIN 53/2019
Perl sockets work like file handles that can span across a network or the entire Internet.

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
03 $select = IO::Select->new();
05 $select->add($socket1);
06 $select->add($socket2);
07 $select->add($socket3);
08 $select->add($socket4);
10 @ok_to_read = $select->can_read($timeout);
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 are tcp or udp.
  • Type – The type of connection you'd like to establish, the options being SOCK_STREAM for tcp data, SOCK_DGRAM for udp connections, or SOCK_SEQPACKET for sequential data packet connections. I'll be using tcp and the SOCK_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
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

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy ADMIN Magazine

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

  • Visualizing time series data
    Graphite converts confusing columns of time series data into handy diagrams, showing trends in operating system and application metrics at a glance.
  • TCP Stealth hides open ports
    Port scans for finding vulnerable services are nothing new, and port knocking as a defense has been around for a while, too. TCP Stealth tries to do something similar, but it takes a more sophisticated approach. We take a closer look.
  • Asynchronous PostgreSQL
    Programming database queries in Perl is pretty easy thanks to the DBI module – but beware, where simplicity reigns, there be dragons.
  • Graphite: Collect and Visualize Numeric Data

    Graphite converts confusing columns of time series data into handy diagrams, showing trends in operating system and application metrics at a glance.

  • Secure microservices with centralized zero trust
    SPIFFE and SPIRE put strong workload identities at the center of a zero-trust architecture. They improve reliability and security by taking the responsibility for identity creation and management away from individual services and workloads.
comments powered by Disqus