Perl socket
last modified August 24, 2023
Perl socket tutorial shows how to work with sockets in Perl. Socket programming is low-level. The purpose of the tutorial is to introduce network programming including these low-level details. There are higher-level APIs that may be more practical in real-world scenarios.
Network protocols
TCP/IP is a suite of protocols used by devices to communicate over the Internet and most local networks. TCP is more reliable, has extensive error checking, and requires more resources. It is used by services such as HTTP, SMTP, or FTP. UDP is much less reliable, has limited error checking, and requires less resources. It is used by services such as VoIP.
Perl socket modules
The Socket
module provides networking constants and support
functions.
The IO::Socket::INET
provides an object interface to creating and
using sockets in the AF_INET
domain; it is used with IPv4 adresses.
The IO::Socket::IP
is a module for working with both IPv4 and IPv6
adresses.
Perl UDP socket example
UDP is a communication protocol that transmits independent packets over the network with no guarantee of arrival and no guarantee of the order of delivery. One service that used UDP is echo.
The Echo Protocol is a service in the Internet Protocol Suite defined in RFC 862. The Echo Protocol can use the TCP or the UDP on the port number 7. The server sends back an identical copy of the data it received.
We set up an echo service on a local Debian system.
$ cat /etc/services | grep echo | head -4 echo 7/tcp echo 7/udp echo 4/ddp # AppleTalk Echo Protocol
Port 7 is reserved for echo service.
Due to security concerns, the echo service is disabled in most cases on publicly available computers. Therefore, we create our own service in a local network.
We start the echo service on a different computer in a local network.
# apt install xinetd
We install the xinetd
package. The package contains the the
xinetd
daemon, which is a TCP wrapped super service for accessing
a subset of popular network services including echo, FTP, IMAP, and telnet.
... # This is the udp version. service echo { disable = no type = INTERNAL id = echo-dgram socket_type = dgram protocol = udp user = root wait = yes }
In the /etc/xinetd.d/echo
file, we set the disable
option to no.
# systemctl start xinetd
We start the service.
#!/usr/bin/perl use 5.30.0; use warnings; use IO::Socket::INET; my $addr = 'core9'; my $port = 7; my $msg = shift || "hello"; my $sock = IO::Socket::INET->new( Domain => AF_INET, PeerAddr => $addr, PeerPort => $port, Proto => 'udp', ) or die "failed to create socket: $!\n"; $sock->send("$msg\n", 0); my $data = <$sock>; say "$data"; $sock->close();
The example sends a message to the echo service on a local network computer. The computer echoes back the message.
my $addr = 'core9'; my $port = 7;
We define the network address and port.
my $sock = IO::Socket::INET->new( Domain => AF_INET, PeerAddr => $addr, PeerPort => $port, Proto => 'udp', ) or die "failed to create socket: $!\n";
We create a new socket with IO::Socket::INET
. We specify the
domain, address, port, and protocol.
$sock->send("$msg\n", 0);
We send a message on the socket.
my $data = <$sock>; say "$data";
We read and print the response.
$sock->close();
We close the socket with close
.
$ ./echo_client.pl cau cau
Perl socket QOTD
A quote of the day service is a debugging and measurement tool is. The quote of the day service simply sends a short message without regard to the input.
$ cat /etc/services | grep qotd qotd 17/tcp quote
Port 17 is reserved for the quote of the day service.
#!/usr/bin/perl use 5.30.0; use warnings; use IO::Socket::INET; my $sock = IO::Socket::INET->new("djxmmx.net:17") or die "failed to create socket: $!\n"; $sock->send('', 0); while (<$sock>) { print $_; } print "\n"; $sock->close();
The example creates a client program that connects to a QOTD service.
my $sock = IO::Socket::INET->new("djxmmx.net:17") or die "failed to create socket: $!\n";
A TCP socket is created to the specified address and port. If the protocol is not specified, the TCP is assumed. Note that services like this are ephemeral; they may be removed anytime.
$sock->send('', 0);
We send an empty message to the socket.
$ ./qotd.pl "Here's the rule for bargains: "Do other men, for they would do you." That's the true business precept." Charles Dickens (1812-70)
Perl socket WHOIS example
WHOIS service allows use to find information about domain name registration, such as the registration date and domain name age, or contact details of the person or organization owning the domain.
On the modern Internet, WHOIS services are typically communicated using the Transmission Control Protocol (TCP). Servers listen to requests on the well-known port number 43.
Note that the whoise services are often limited to a small set of domains.
#!/usr/bin/perl use 5.30.0; use warnings; use IO::Socket::INET; my $domainName = shift || "example.me"; my $host = "whois.nic.me"; my $port = 43; my $sock = IO::Socket::INET->new( PeerHost => $host, PeerPort => $port, Proto => 'tcp', ) or die "failed to create socket: $!\n"; say 'socket created'; my $size = $sock->send("$domainName\n", 0); say "Sent data of length: $size"; say '-------------------------'; while (<$sock>) { print $_; } close $sock;
In the example, we query a WHOIS service about the given domain.
$ ./whs.pl tada.me socket created Sent data of length: 8 ------------------------- Domain Name: TADA.ME Registry Domain ID: D425500000006230617-AGRS Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2021-01-11T19:57:02Z Creation Date: 2017-09-09T18:21:42Z Registry Expiry Date: 2021-09-09T18:21:42Z ...
Perl socket HEAD request
A HEAD request is an HTTP GET request without a message body. The header of a request/response contains metadata, such as HTTP protocol version or content type.
#!/usr/bin/perl use 5.30.0; use warnings; use IO::Socket::INET; my $addr = 'webcode.me:80'; my $req = "HEAD / HTTP/1.0\r\n\r\n"; my $sock = IO::Socket::INET->new( Domain => AF_INET, PeerAddr => $addr, ) or die "failed to create socket: $!\n"; $sock->send($req, 0); while (<$sock>) { print $_; } $sock->close();
In the example, we send a HEAD request to webcode.me.
$sock->send("HEAD / HTTP/1.0\r\n\r\n", 0);
A head request is issued with the HEAD
command followed by the
resource URL and HTTP protocol version. Note that the \r\n
characters are mandatory part of the communication process. The details are
described in RFC 7231
document.
$ ./head_req.pl HTTP/1.1 200 OK Server: nginx/1.6.2 Date: Wed, 30 Jun 2021 12:57:05 GMT Content-Type: text/html Content-Length: 348 Last-Modified: Sat, 20 Jul 2019 11:49:25 GMT Connection: close ETag: "5d32ffc5-15c" Accept-Ranges: bytes
Perl socket GET request
The HTTP GET method requests a representation of the specified resource. Requests using GET should only retrieve data.
#!/usr/bin/perl use 5.30.0; use warnings; use IO::Socket::INET; my $addr = 'webcode.me:80'; my $req = "GET / HTTP/1.0\r\n" . "Host: webcode.me\r\n" . "User-Agent: Perl client\r\n\r\n"; my $sock = IO::Socket::INET->new( PeerAddr => $addr, ) or die "failed to create socket: $!\n"; $sock->send($req, 0); while (<$sock>) { print $_; } $sock->close();
The example reads the home page of the webcode.me using a GET request.
my $req = "GET / HTTP/1.0\r\n" . "Host: webcode.me\r\n" . "User-Agent: Perl client\r\n\r\n";
We write a simple GET request.
Perl socket send mail
To send an email via socket, we utilize the SMTP commands, such as HELO, MAIL FROM, and DATA.
#!/usr/bin/perl use 5.30.0; use warnings; use IO::Socket::INET; my $from = 'john.doe@example.com'; my $to = 'root@core9'; my $name = 'John Doe'; my $subject = 'Hello'; my $body = 'Hello there'; my $addr = 'core9:25'; my $req = "HELO core9\r\n" . "MAIL FROM: $from\r\n" . "RCPT TO: $to\r\n" . "DATA\r\n" . "From: $name\r\n" . "Subject: $subject \r\n" . "$body\r\n.\r\n" . "QUIT\r\n"; my $sock = IO::Socket::INET->new( PeerAddr => $addr, ) or die "failed to create socket: $!\n"; $sock->send($req, 0); while (<$sock>) { print $_; } $sock->close();
The example sends an email to a computer on a local network, which hosts an email server.
$ ./send_mail.pl 220 core9 ESMTP Sendmail 8.15.2/8.15.2; Thu, 1 Jul 2021 14:27:19 +0200 (CEST) 250 core9 Hello spartan.local [192.168.0.20], pleased to meet you 250 2.1.0 john.doe@example.com... Sender ok 250 2.1.5 root@core9... Recipient ok 354 Enter mail, end with "." on a line by itself 250 2.0.0 161CRJJv001451 Message accepted for delivery 221 2.0.0 core9 closing connection
We send the email.
From john.doe@example.com Thu Jul 1 14:27:19 2021 Return-Path: <john.doe@example.com> Received: from core9 (spartan.local [192.168.0.20]) by core9 (8.15.2/8.15.2) with SMTP id 161CRJJv001451 for root@core9; Thu, 1 Jul 2021 14:27:19 +0200 (CEST) (envelope-from john.doe@example.com) Date: Thu, 1 Jul 2021 14:27:19 +0200 (CEST) Message-Id: <202107011227.161CRJJv001451@core9> From: John.Doe Subject: Hello To: undisclosed-recipients:; Status: RO Hello there
We check the email on the receiving end.
In this article we have worked with sockets in Perl.
Author
List all Perl tutorials.