Socket Programming With Perl

perl

Sample client

#!/usr/bin/perl -w
use strict;
use Socket;
my ($remote,$port, $iaddr, $paddr, $proto, $line);

$remote  = 'localhost';
$port    = 2345;

$iaddr   = inet_aton($remote)         || die "no host: $remote";
$paddr   = sockaddr_in($port, $iaddr);

$proto   = getprotobyname('tcp');
socket(SOCK, PF_INET, SOCK_STREAM, $proto)    || die "socket: $!";
connect(SOCK, $paddr)    || die "connect: $!";
while (defined($line = <SOCK>)) {
    print $line;
}

close (SOCK)        || die "close: $!";

Sample server

#!/usr/bin/perl -Tw
use strict;
use Socket;
use Carp;
use POSIX ":sys_wait_h";
use Errno;
my $EOL = "\015\012";

my $port = 2345;
my $proto = getprotobyname('tcp');
my $waitedpid = 0;
my $paddr;

sub spawn;  # forward declaration
sub logmsg { print "$0 $$: @_ at ", scalar localtime, "\n" }
sub REAPER {
        local $!;   # don't let waitpid() overwrite current error
        while ((my $pid = waitpid(-1,WNOHANG)) > 0 && WIFEXITED($?)) {
            logmsg "reaped $waitedpid" . ($? ? " with exit $?" : '');
        }
        $SIG{CHLD} = \&REAPER;  # loathe sysV
}
$SIG{CHLD} = \&REAPER;

socket(SERVER, PF_INET, SOCK_STREAM, $proto)    || die "socket: $!";
setsockopt(SERVER, SOL_SOCKET, SO_REUSEADDR, pack("l", 1))     || die "setsockopt: $!";
bind(SERVER, sockaddr_in($port, INADDR_ANY))    || die "bind: $!";
listen(SERVER,SOMAXCONN) || die "listen: $!";

while(1) {
    $paddr = accept(CLIENT, SERVER) || do {
        # try again if accept() returned because a signal was received
        next if $!{EINTR};
        die "accept: $!";
    };
    my ($port, $iaddr) = sockaddr_in($paddr);
    my $name = gethostbyaddr($iaddr, AF_INET);
    logmsg "connection from $name [", inet_ntoa($iaddr), "] at port $port";
    spawn sub {
        $|=1;
        print "Hello there, $name, it's now ", scalar localtime, $EOL;
        exec '/usr/games/fortune'  or confess "can't exec fortune: $!";
    };
    close Client;
}

sub spawn {
    my $coderef = shift;
    unless (@_ == 0 && $coderef && ref($coderef) eq 'CODE') {
        confess "usage: spawn CODEREF";
    }
    my $pid;
    if (! defined($pid = fork)) {
        logmsg "cannot fork: $!";
        return;
    } elsif ($pid) {
        logmsg "begat $pid";
        return; # I'm the parent
    }
    # else I'm the child -- go spawn
    open(STDIN,  "<&Client")   || die "can't dup client to stdin";
    open(STDOUT, ">&Client")   || die "can't dup client to stdout";
    ## open(STDERR, ">&STDOUT") || die "can't dup stdout to stderr";
    exit &$coderef();
}

Another example:

#!/usr/bin/perl
# maillog.serve
use Socket;
$port = "2680";
$remote = "someIP";
$proto = getprotobyname('tcp');
socket(SOCK, PF_INET, SOCK_STREAM, $proto);
setsockopt(SOCK, SOL_SOCKET, SO_REUSEADDR, pack("l",1)); // the first parameter to the pack method is the lower-cased letter L
$iaddr = inet_aton($remote);
$paddr = sockaddr_in($port, $paddr); // Should the second parameter to sockaddr_in be iaddr?
bind(SOCK, paddr);
listen(SOCK, SOMAXCONN);
for (; $paddr = accept(CLIENT, SOCK); close(CLIENT)) {
    print CLIENT $_;
}

Other information:

use Socket;
use IO::Socket;

$socket = IO::Socket::INET->new(
    PeerAddr => 'www.perl.org',
    PeerPort => 'http(80)',
    Proto => 'tcp'
);

$sock = IO::Socket::INET->new(
    PeerAddr => 'localhost:smtp(25)'
);

$sock = IO::Socket::INET->new(
    Listen => 25,
    LocalAddr => 'localhost',
    LocalPort => 9000,
    Proto => 'tcp'
);

sockport()        // returns the port number on the local host
sockhost()        // returns the IP of the local socket
peerport()        // returns the port number of the remote host
peerhost()        // returns the IP of the remote host
timeout([val])
sockopt(OPT [,VAL])
sockdomain()    // returns the numerical number for socket domain
            // For a AF_INET, the value will be &AF_INET
socktype()        // returns the numerical number for socket type
            // For a SOCK_STREAM socket, the value &SOCK_STREAM is returned

inet_aton    HOSTNAME    // Takes a hostname or an IP address and 
                    // converts it to numeric form (structure) sockaddr_in

inet_ntoa    IP_ADDR        // Takes a numeric form (structure) (returned by inet_aton)
                    // and converts it to dotted IP address.

INADDR_ANY
INADDR_BROADCAST
INADDR_LOOPBACK
INADDR_NONE            // represent invalid IP address.

sockaddr_in(PORT, ADDRESS)    // pack and return a sockaddr_in structure
sockaddr_in(SOCKADDR_IN)    // unpack and return a list (port, address)

$proto = getprotobyname('udp');        // returns the protocol number for given protocol
$iaddr = gethostbyname('xyz.com');    // returns the internal address for given hostname/IP.
$port = getservbyname('time','udp');    // returns the port number for given service and protocol

$peer_host = gethostbyaddr($iaddr, AF_INET);
$peer_addr = inet_ntoa($iaddr);
($port,$iaddr) = sockaddr_in(getpeername(socketHandle));

socket(SOCKFD, DOMAIN, TYPE, PROTOCOL);
connect(SOCKFD, NAME);    // NAME should be a packed address of appropriate type
listen(SOCKFD, QUEUESIZE);
accept(NEWSOCK,GENERICSOCK);
send(SOCKFD, MSG, FLAGS)
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License