Network Programming with Perl
Perl has been called the glue that holds the Internet together because it is an extremely powerful text processing and CGI programming language. Although Perl was designed in the beginning to be a text manipulation language, it has evolved into a potent multi-purpose programming language. One area in which Perl has shown its power is that of network programming.
Perl makes network programming easy by providing built-in functions that can be used to create low-level client/server programs from scratch. Also, many modules are freely available that make programming common networking tasks simple and quick. These tasks include pinging remote machines, TELNET and FTP sessions. This article presents examples of each of these types of network programs.
Client/server network programming requires a server running on one machine to serve one or more clients running on either the same machine or different machines. These different machines can be located anywhere on the network.
To create a server, simply perform the following steps using the built-in Perl function indicated:
Create a socket with socket.
Bind the socket to a port address with bind.
Listen to the socket at the port address with listen.
Accept client connections with accept.
Establishing a client is even easier:
Create a socket with socket.
Connect (the socket) to the remote machine with connect.
Several other required functions and variables are defined in the Socket.pm module. This module is probably already installed on your machine, but if not, it is available at the Comprehensive Perl Archive Network (CPAN), the official Perl source code repository (see Resources). To use this module in our programs, the following statement is required at the top of the program:
use Socket;
This statement will locate the file Socket.pm and import all of its exported functions and variables.
All examples in this article use modules that are available at no cost from CPAN.
Perl modules are usually self-documenting. If the author of the module follows the generally accepted rules of creating a Perl module, they will add Plain Old Documentation (POD) to the module's .pm file. One way to view the POD for the Socket module (assuming Perl and Socket.pm were installed correctly) is to execute the following at the shell:
perldoc Socket
This command displays Socket.pm's POD converted to a man page. The output is a relatively thorough discussion of the functions and variables defined in this module.
Another way to view the documentation is to convert the POD to text using:
pod2text \ /usr/lib/perl5/i686-linux/5.00404/Socket.pm | more
The program pod2text is included in the Perl distribution, as are the programs pod2html, pod2man, pod2usage and pod2latex.
Our first programming example is a simple server running on one machine that can service only one client program at a time connecting from the same or a different machine. Recall that the steps for creating a server were to create a socket, bind it to a port, listen at the port and accept client connections.
Listing 1, server1.pl, is the source code for this simple server. First, it is generally a good idea to compile using Perl's strict rules:
use strict;
This requires all variables to be declared with the my function before they are used. Using my may be inconvenient, but it can catch many common syntactically correct yet logically incorrect programming bugs.
The variable $port is assigned the first command-line argument or port 7890 as the default. When choosing a port for your server, pick one that is unused on your machine. Note that the only way to ensure you select a port that does not have a predefined use is to look at the appropriate RFC (see Resources).
Next, the socket is created using the socket function. A socket is like a file handle—it can be read from, written to or both. The function setsockopt is called to ensure that the port will be immediately reusable.
The sockaddr_in function obtains a port on the server. The argument INADDR_ANY chooses one of the server's virtual IP addresses. You could instead decide to bind only one of the virtual IP addresses by replacing INADDR_ANY with
inet_aton("192.168.1.1")
or
gethostbyname("server.onsight.com")
The bind function binds the socket to the port, i.e., plugs the
socket into that port. Then, the listen function causes the server
to begin listening at the port. The second argument to the listen
function is the maximum queue length or the maximum number of
pending client connections. The value SOMAXCONN
is the maximum queue length for the machine being used.
Once the server begins listening at the port, it can accept client connections using the accept function. When the client is accepted, a new socket is created named CLIENT which can be used like a file handle. Reading from the socket reads the client's output and printing to the socket sends data to the client.
To read from a file handle or socket in Perl, wrap it in angle brackets (<FH>). To write to it, use the print function:
print SOCKET;
The return value of the accept function is the Internet address of the client in a packed format. The function sockaddr_in takes that format and returns the client's port number and the client's numeric Internet address in a packed format. The packed numeric Internet address can be converted to a text string representing the numeric IP using inet_ntoa (numeric to ASCII). To convert the packed numeric address to a host name, the function gethostbyaddr is used.
Let's assume all of the servers referred to in this article are started on the machine named server.onsight.com. To start the server on this machine, execute:
[james@server networking]$ server1.pl SERVER started on port 7890
The server is now listening at port 7890 on server.onsight.com, waiting for clients to connect.











This week 5 lucky Members will receive a copy of The Official Ubuntu Server Book by Benjamin Mako Hill and Linux Journal's very own Kyle Rankin. No entry necessary. Check back here early next week to find out who the lucky Online Members are.




Comments
EOF character at Server?
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
network programing with perl
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
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?
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
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 -
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
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
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
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
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
You could use bytes module see http://perldoc.perl.org/bytes.html
Minor correction to server1.pl example
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
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
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
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
Absolute Good thing.. Thanks for all the info presented.
Fork vs Thread
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
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
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
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
a good guide to the world of the networks!
Re: Strictly On-Line: Network Programming with Perl
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
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
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
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
Keep up the good job of showing a wonderful way to perl network programming beginners.
Hey! This one's simply too
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
Post new comment