Network Programming with Perl

Using Perl to make network task is easy—here's how.
A Simple Client

Listing 2.

Listing 2, client1.pl, shows a simple client. The first command-line argument to this program is the host name to which it should connect, which defaults to server.onsight.com. The second command-line argument is the port number which defaults to 7890.

The host name and the port number are used to generate the port address using inet_aton (ASCII to numeric) and sockaddr_in. A socket is then created using socket and the client connects the socket to the port address using connect.

The while loop then reads the data the server sends to the client until the end-of-file is reached, printing this input to STDOUT. Then the socket is closed.

Let's assume all of the clients are started on the the machine named client.avue.com, although they could be executed from any machine on the network. To execute the client, type:

[james@client networking]$ client1.pl server.onsight.com
Hello from the server: Tue Oct 27 09:48:40 1998

The following is the standard output from the server:

got a connection from: client.avue.com [192.168.1.2]

Perl Makes Life Easy

Creating sockets using the functions described above is good when you want to control how the socket is created, the protocol to be used, etc. But using the functions above is too hard; I prefer the easy way—IO::Socket.

The module IO::Socket provides an easy way to create sockets which can then be used like file handles. If you don't have it installed on your machine, it can be found on CPAN. To see this module's POD, type:

perldoc IO::Socket
A Simple Server Using IO::Socket

Listing 3.

Listing 3, serverIO.pl, is a simple server using IO::Socket. A new IO::Socket::INET object is created using the new method. Note that the arguments to the method include the host name, port number, protocol, queue length and an option indicating we want this port to be immediately reusable. The new method returns a socket that is assigned to $sock. This socket can be used like a file handle—we can either read the client output from it, or write to it by sending data to the client.

A client connection is accepted using the accept method. Note the accept method returns the client socket when evaluated in scalar context:

$new_sock = $sock->accept()

and returns the client's socket and the client's IP address when evaluated in list context:

($new_sock, $client_addr) = $sock->accept()
The client address is computed and printed the same as in Listing 1, server1.pl. Then the socket associated with that client is read until end-of-file. The data read is printed to STDOUT. This example illustrates that the server can read from a client using < > around the socket variable.

A Simple Client Using IO::Socket

Listing 4.

Listing 4, clientIO.pl, is a simple client using IO::Socket. This time, a new object is created that connects to a host at a port using the TCP protocol. Ten strings are then printed to that server, then the socket is closed.

If the server in Listing 3, serverIO.pl, is executed and then the client Listing 4, clientIO.pl, connects, the output would be:

[james@server networking]$ serverIO.pl
got a connection from: client.avue.com [192.168.1.2]
hello, world: 1
hello, world: 2
hello, world: 3
hello, world: 4
hello, world: 5
hello, world: 6
hello, world: 7
hello, world: 8
hello, world: 9
hello, world: 10
Bidirectional Communication

It is possible to create servers and clients that communicate with one another in both directions. For instance, the client may send information to the server, then the server may send information back to the client. Therefore, network programs can be written so that the server and client follow some predetermined protocol.

Listing 5.

Listing 5, server2way.pl, shows how a simple server can be created to read a command from a client, then print out an appropriate response to the client. The module Sys::Hostname provides a function named hostname that returns the host name of the server. To insure output is seen as we print, IO buffering is turned off for the STDOUT file handle using the autoflush function. Then a while loop is executed that accepts connections. When a client connects, the server reads a line from the client, chopping off the newline character. Then a switch statement is executed. (The switch is cleverly disguised as a foreach loop, which happens to be one of my favorite ways of writing a switch.) Depending on the input entered by the client, the server outputs an appropriate response. All lines from the client are read until end-of-file.

Listing 6.

Listing 6, client2way.pl, shows the companion client. A connection to the server is made, then the client prints a few commands to the server reads the response and prints the response to STDOUT.

The following is the output of the client code in Listing 6:

[james@client networking]$ client2way.pl
server.onsight.com
Hi
server.onsight.com
Tue Oct 27 15:36:19 1998
DEFAULT
______________________

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

INSOMNIA_THE MIDNIGHT PROGRAMMING CONTEST

Anonymous's picture

THE MIDNIGHT PROGRAMMING CONTEST...
www.insomnia.cognizance.org.in
Starts on : 27th March, 9:00 PM
Cash prizes worth Rs.30,000 on stake for this round.

(PS: Problems of previous rounds are available for practice.)

EOF character at Server?

PaulCEIRE's picture

I'm trying to build a server that will read on a string of characters, parse them and return an appropriate result to the client. The problem I have is that the application that will act as the client re-uses the same connection for all requests and there is no 'carriage return' or line feed at the end of each request, so my server does not know that the full request has been received and will just wait for an EOF character and hang.
I have re-created this scenario by building 2 client perl programs, 1 with the carriage return and 1 without.
As I have no control over how my application submits these strings I need to find a solution on the server side. The first 4 digits of each request string give the lentgh of the proceeding data, is there any way I can append and EOF character to the request data after I've received it on my server?

Client1:
$msg="00110100303C120";
$sock->send($msg);

Client2:
$msg="00110100303C120\n";
$sock->send($msg);

Server:
# While there is data to read from the connection
while (defined ($buf = <$new_sock>)) {
print $buf;
}

Thanks

Just read the first 4 bytes

jlhm's picture

Just read the first 4 bytes using:

read($new_sock, $length. 4);

then use the $length to read the actual data:
You might need to convert the $length data to actual decimal value if needed using unpack().

read($new_sock, $data, $length);

network programing with perl

Anonymous's picture

hi,
i am a newbie in perl programing. i found this client-server program on the net and wanted to try it out. The client will simply connect to the server and send a line "hello there" to the server which will then print it out there.

############################
client
#############################

#!/usr/bin/perl
# client.plx
use warnings;
use strict;
use IO::Socket;

my $client = IO::Socket::INET->new( 
					PeerAddr => 'localhost',
					PeerPort => '7890',
					Proto => 'tcp'
                                  )or die "could not create socket: $!\n";

print "hi\n";
print $client "Hello there!\n";
close $client;
###########################

but the problem is that whenever i try to run the client, it says "could not create socket: Unkown error". the server runs perfectly. can someone pls point out the mistake here. btw i am currently referring "beginner's perl : simon cozens" and the client program given there are the same as above.

thank you.

I get the same error

Anonymous's picture

I get the same error sometime, to solve it I need to enter in the actual IP address of my host instead of 'localhost', ie.:
PeerAddr => '127.0.0.1',
PeerPort => '7890',
Proto => 'tcp'

how to keep client session open in Perl?

Thuy's picture

I have a perl script while telnet to a remote machine from linux local machine, run commands, and return the results.
After the perl script is run completely, the telnet session is closed.
But, I want to keep the tenet session open. Can anyone tell me how to do it in Perl programs?

server2way.pl and client2way.pl

tcltkdev's picture

server2way.pl (Listing 5) and client2way.pl (Listing 6) works fine if both are ran on my pc but when I ran server2way.pl on another pc on the network (both Windows XP) I get this error on the client side:

no socket :Unknown error at client2way.pl line 14.

and this is line 14:

$sock or die "no socket :$!"; # Connect to server

I want to use this in our on going project.

Please help.

Network programming -

Anonymous's picture

Few questions -

How do I know what ports (possible no of ports also) to use for the server and the client over TCP/IP, is there some range? We are using c++ for network/socket programming.

Thanks for your help.

Odd accept() behavior

Owen LaGarde's picture

I noticed this when I converted Listings 6 (client) and 8 (server) to use EOLN delimited IO
(to better examine the behavior of concurrent stream sessions). This was initially done
because Listing 8 did not wait for new sessions after the first was closed. After the 1st
client exited accept() would return undef until another request was queued but didn't block
while waiting for the queue event. Eventually I just wrapped the outer while() in another
"while( ; sleep 2)" to give myself time to check the socket queue and match
incoming requests to accept() results. This revealed yet more oddities. Note that the
'Listen' parameter is set to SOMAXCONN (128 for my RHEL box and perl 5.8.5) for both forms
of new() socket operators. Any ideas on the following 3 oddities?

- Using IO::Socket::INET sockets -- the third concurrent session request hangs unprocessed
until one of the previous [still open] sessions exit, ie., when more than 2 open sessions
exist accept() blocks until there is only 1 open session, then processes the next waiting
request as expected.

- Using IO::Socket::UNIX sockets -- many concurrent sessions can be opened but once any of
these are closed accept() hangs until all other sessions are closed, ie., if open sessions
exist and one is closed accept() blocks until all are closed, then processes request(s) --
but not as expected, see bullet 3 below.

- Using either form of sockets -- prior to opening any sessions accept() blocks, waits for
requests to queue, and processes the first queued request as expected, but subsequent calls
to accept() return undef unless another request is queued, ie., accept() behaves as if the
O_NONBLOCK bit is being automatically set on the original socket at or after the first call.

###################################################
## The Client
###################################################

#!/usr/bin/perl -w
use strict;
use IO::Socket;
#use Carp;
#use Data::Dumper;

# Domain sockets
my $sock = new IO::Socket::UNIX( Peer => '/tmp/mysock',
Type => SOCK_STREAM ) or die $!;

## IP sockets
#my $sock = new IO::Socket::INET( PeerAddr => 'localhost', PeerPort => '7890',
# Proto => 'tcp'); $sock or die "no socket :$!";

my $buf;
while( $buf = <> ) {
chomp $buf;
print $sock "$buf\n";
print "$0 ($$): ", scalar localtime(), " sent: [$buf]\n";
$buf = scalar <$sock>;
chomp $buf;
print "$0 ($$): ", scalar localtime(), " received: [$buf]\n";
}
close $sock;

###################################################
## The server
###################################################

#!/usr/bin/perl -w
use strict;
use IO::Socket;
use POSIX qw(:sys_wait_h);
#use Carp;
#use Data::Dumper;

sub REAP {
1 until( -1 == waitpid( -1, WNOHANG ) );
$SIG{CHLD} = \&REAP;
}
$SIG{CHLD} = \&REAP;

# Domain sockets
unlink '/tmp/mysock';
my $sock = new IO::Socket::UNIX( Local => '/tmp/mysock', Type => SOCK_STREAM,
Listen => SOMAXCONN, Reuse => 1 ) or die $!;

## IP sockets
#my $sock = new IO::Socket::INET( LocalHost => 'localhost', LocalPort => 7890,
# Proto => 'tcp', Listen => SOMAXCONN, Reuse => 1) or die $!;

STDOUT->autoflush(1);

my( $new_sock, $child, $buf );
while( 1 ) {
while( $new_sock = $sock->accept() ) {
if( $child = fork ) {
close $new_sock
} elsif( defined( $child ) ) {
close $sock;
while( defined( $buf = <$new_sock> ) ) {
chomp $buf;
print "$0 ($$): ", scalar localtime(), " received: [$buf]\n";
sleep 1;
print "$0 ($$): ", scalar localtime(), " sending: [$buf]\n";
print $new_sock "$buf\n";
}
exit
} else {
die "$0 ($$): fork: $!"
}
}
sleep 2
}

###################################################
## END
###################################################

Re: odd accept() behavior

Owen LaGarde's picture

BTY: no, it isn't the "while( defined( $buf = <$new_sock> ) )..." at line 32 of the server, where the child proc reads the copied socket. Yes, changing this to an if() will remove the behavior -- by enforcing line-only processing of the socket contents -- but this doesn't explain why the behavior only occurs when sessions=3 for IP sockets or when the first child exit occurs for Domain sockets.

clientfork.pl is not working on XP

lakshmi's picture

hi there,

I'm trying to execute client fork.pl on my xp machine with both client and server running on the same machine but it doesn't seem to be working. when i enter input at client, it simply accepts the input and then nothing happens.

Can anybody help me with this.

Thanks in advance,
lakshmi.

Sending binay data to the server

Anonymous's picture

Can the print statement be used to send binary data to the server? For example: to send the message to the server, you would have a statement PRINT $client $message.

If $message = 0xFF ;

what would be sent to the server? Is it the ASCII representation of the number 255? How can I send the 8-bit binary representation of the numner 255 and not one byte for 2, one byte for 5, and another byte for 5 ? Any help would be appreciated.
Thanks.

perl send binary through socket

Anonymous's picture

You could use bytes module see http://perldoc.perl.org/bytes.html

Minor correction to server1.pl example

Allan's picture

There is a minor error at the end of the server1.pl example:
# send them a message, close connection
print CLIENT "Hello from the server: ",
close CLIENT;

As stated, there is a write to closed socket error and no message passed to the client. One fix is to replace the "," with ";" on the print line.

Another fix

RyDer's picture

Another fix is to put this on the end of the line:

print CLIENT "Hello from the server: ", scalar localtime, "\n";

because on the response of the server to the client shows a time stamp.

Be care.

Another fix

RyDer's picture

Another fix is to put this on the end of the line:

print CLIENT "Hello from the server: ", scalar localtime, "\n";

because on the response of the server to the client shows a time stamp.

Be care.

A very good example set for

Shilpa's picture

A very good example set for beginners. I am interested in knowing more about how I could use perl and start a program as server and which takes an input text from client and processes it and returns the result to client. Something using VEC and SELECT per commanda. I am woring on this code I have which uses all this. If you have any examples for that please let me know.

Thanks,

Absolute Good thing.. Thanks

Anonymous's picture

Absolute Good thing.. Thanks for all the info presented.

Fork vs Thread

lintastic's picture

This tutorial was excelent. It was clear, concise, and informative. Although, I did have one question. What are the bennefits of using fork over thread? In most cases I know that creating a thread has most of the same bennefits of using fork but without the extra overhead. Why would one want to use fork in a web server as opposed to thread? Thanks!

Fantastic

jayanthi's picture

I really got interested in learning network programming after looking in to this article. It is really great on you. Can you suggest us the sites used for learning in depth of network programming with the real time examples

great help

jatin patni's picture

Hi, i have been looking around lately for some networking related tutorials and i admit that this place is actually exactly what i was looking for.
Thanks.

PS: Beginner in perl.

Re: Strictly On-Line: Network Programming with Perl

Anonymous's picture

Hi James,

I'm very new to PERL. I want to know about socket programming in PERL. I have to make chat module in my site. where is any user want to chat with somebody then he/se can be able to send alert message to that perticular user. if he/she accept the request then new chat window should open both side without any page refreshment.
I hope your guidance will be important for me.

regards,

Bharat

Re: Strictly On-Line: Network Programming with Perl

Anonymous's picture

a good guide to the world of the networks!

Re: Strictly On-Line: Network Programming with Perl

Anonymous's picture

I was really in big trouble with perl' sockets programming, this tutorial was proved to be a big help for me to get stated writing programs that use sockets in perl.....thnx for such a nice tutorial...

Re: Strictly On-Line: Network Programming with Perl

Anonymous's picture

Great article, most of it worked on my FBSD server to.

Thanks alot, keep up the good work.

- Stian

Re: Strictly On-Line: Network Programming with Perl

Anonymous's picture

Hi James,

A very informative site. Also very elegantly written. Easy to understand and implement.

Was a big help to me.

Thanks a bunch.

Cheers,

Arun Krishnan

HI

Anonymous's picture

Yes really Arun
I'm very new to this Socket programming in perl
Please let me know , if you are familiar with this
Thanks and regards
Jey

good job

kararu's picture

Keep up the good job of showing a wonderful way to perl network programming beginners.

Hey! This one's simply too

Shraddha's picture

Hey!

This one's simply too good...was yearning for something on networking concepts...couldn ask better than this one.

Lets keep the good work coming!

Best Regards,
Shraddha

White Paper
Linux Management with Red Hat Satellite: Measuring Business Impact and ROI

Linux has become a key foundation for supporting today's rapidly growing IT environments. Linux is being used to deploy business applications and databases, trading on its reputation as a low-cost operating environment. For many IT organizations, Linux is a mainstay for deploying Web servers and has evolved from handling basic file, print, and utility workloads to running mission-critical applications and databases, physically, virtually, and in the cloud. As Linux grows in importance in terms of value to the business, managing Linux environments to high standards of service quality — availability, security, and performance — becomes an essential requirement for business success.

Learn More

Sponsored by Red Hat

White Paper
Private PaaS for the Agile Enterprise

If you already use virtualized infrastructure, you are well on your way to leveraging the power of the cloud. Virtualization offers the promise of limitless resources, but how do you manage that scalability when your DevOps team doesn’t scale? In today’s hypercompetitive markets, fast results can make a difference between leading the pack vs. obsolescence. Organizations need more benefits from cloud computing than just raw resources. They need agility, flexibility, convenience, ROI, and control.

Stackato private Platform-as-a-Service technology from ActiveState extends your private cloud infrastructure by creating a private PaaS to provide on-demand availability, flexibility, control, and ultimately, faster time-to-market for your enterprise.

Learn More

Sponsored by ActiveState