Perlfect Solutions
 

Perl, Sockets and TCP/IP Networking.

An simplified introduction to sockets

Sockets are a mechanism that allows programs to communicate, either on the same machine or across a network. The way it works is pretty simple: Each machine on a network is identified by some address. In this tutorial we will talk about tcp/ip networking, so by network address we mean an IP address. (like 192.168.4.4) Apart from the IP address that specifies a machine, each machine has a number of ports that allow handling multiple connections simultaneously.

A program that wishes to receive a connection from another program, asks the operating system to create a socket and bind it to some port. Then the program sits and listens on the socket it has created to receive incoming connections. The other program also creates a socket for communicating witht he receiver. The caller needs to specify the IP address and the port number of the receiving end. If all goes well, and as we will see shortly, the two programs establish a communication through the network using their sockets. The two programs may exchange information, each by writing to and reading from the socket it has created.

Can I do this with Perl?

Sure. Perl provides support for the socket API natively. Although the interface is not that bad anyway, there is also a very convenient module, IO::Socket that works like a wrapper on the native API and provides a simpler and easier way to deal with sockets. We'll use IO::Socket in this tutorial to demonstrate writing two simple programs that communicate with sockets.

The Receiver

The first thing we need to do is to create a socket. We will use it to receive connections. The code below shows how to create a receiving socket. Note that we need to specify the local hostname and the port to which the socket will be bound. Of course, if the port is already in use this call will fail. Also note the 'Listen' parameter: this is the maximum number of connections that can be queued by the socket waiting for you to accept and process them. For the time being we will only accept a maximum of one connection at any time. (This means that a connection attempt while we're dealing with another connection, will return with an error like 'connection refused') Finally the 'Reuse' option tells the system to allow reuse of the port after the program exits. This is to ensure that if our program exits abnormally and does not properly close the socket, running it again will allow opening a new socket on the same port.

1 use IO::Socket; 2 my $sock = new IO::Socket::INET ( 3 LocalHost => 'thekla', 4 LocalPort => '7070', 5 Proto => 'tcp', 6 Listen => 1, 7 Reuse => 1, 8 ); 9 die "Could not create socket: $!\n" unless $sock;

Now the socket is ready to receive incoming connections. To wait for a connection, we use the accept() method which will return a new socket through which we can communicate with the calling program. Information exchange is achieved by reading/writing on the new socket. The socket can be treated like a regular filehandle.

10 my $new_sock = $sock->accept(); 11 while(<$new_sock>) { 12 print $_; 13 } 14 close($sock);

The Caller

The other side of the communication is even simpler. All we need to do is to create a socket specifying the remote address and port. The constructor will return a socket object after the connection has been etablished, and we may start sending data right away by writing onto the socket like any other filehandle.

1 use IO::Socket; 2 my $sock = new IO::Socket::INET ( 3 PeerAddr => 'asomatos', 4 PeerPort => '7070', 5 Proto => 'tcp', 6 ); 7 die "Could not create socket: $!\n" unless $sock; 8 print $sock "Hello there!\n"; 9 close($sock);

Go ahead and try it!

You can easily try out the example programs above. All you need to do is execute the receiver first and then the sender. On the receiver end, you will see the line "Hello there!" printed on the terminal screen. If you do not have a network, you can still use 'localhost' for the hostname of both the receiver and caller just to test it out.

Synchronization

An important issue to consider in this style of communication is that the two ends must follow a commonly-agreed procedure of data exchange. Otherwise it is very easy to end up in a deadlock situation where either both ends try to read, or both ends try to write. Ther is no way to guess whether the other end has finshed sending data, unless there is some protocol of communication between them that denotes logical sections of the communication in the contents of the transmitted messages. In the example above, the model is very simplistic: The caller sends a message and closes its end of the connection, while the receiver just reads the data until it's all finished.

Usually client-server transactions consist of a caller (the client) sending a request, followed by the receiver (server) sending back a reply. In order for the server to understand when the request is finished, there is some agreed marker (such as two consecutive empty lines, or a line saying "END REQUEST") that denotes the last line in the request. The server, starts sending its reply only after this line has been received, and afterwards closes the socket. The receiver, after sending the entire request switches to reading until the socket is closed, so it will receive the reply. More complex schemes can be established in a similar mannere, according to your needs and taste. What is important is to make sure that the two ends of the communication have a way of knowing when to speak and when to listen, thus avoiding the possibility of getting locked up.

Online Documentation/Tutorials

  • Network Programming in Perl - a well-written introduction to network programming with practical examples.
  • The documentation of the Socket and IO::Socket modules that comes with your perl distribution should be a valuable reference.
  • There's also an article on filhandle multiplexing with select() in which we describe a method commonly use to manage multiple sockets on the same thread.

Digg! Save This Page

Comments

32to28   

Posted at 5:27pm on Monday, March 5th, 2007

Great article, helps a ton. Great for beginners, can modify it to your own chat application. Thanks.

Akshat Mithal   

Posted at 11:16am on Sunday, April 8th, 2007

Thanks it was a great note..

I created my own successful script for the first time.

Thanks

Soy4soy   

Posted at 12:14pm on Friday, April 20th, 2007

This helped me pick perl up where I left off years ago... thanks!

rajiv   

Posted at 11:21pm on Thursday, May 17th, 2007

Thanks it was a great note..

Emin Gabrielyan   

Posted at 6:14am on Monday, May 21st, 2007

The listener script of the example does not work with UDP

Emin Gabrielyan   

Posted at 12:35pm on Monday, May 21st, 2007

Here is a script for receiving and printing UDP packets:
===

use IO::Socket;
$server = IO::Socket::INET->new(LocalPort => '5060',
Proto => "udp")
or die "Couldn't be a udp server on port $server_port : $@n";

my $datagram;
my $MAX_TO_READ = 2048;

while ($user=$server->recv($datagram,$MAX_TO_READ))
{
print "---n";
print $datagram;
}

close($server);


===
Here is the screenshot of the script, which receives REGISTER messages from a SIP phone:
===
$ perl a5.txt
---
REGISTER sip:192.168.1.8 SIP/2.0
Via: SIP/2.0/UDP 192.168.1.10;branch=z9hG4bK994c1f6fcb609bef
From: ;tag=dace27af55f4699b
To:
Contact:
Supported: replaces
Call-ID: 599f793881392bc1@192.168.1.10
CSeq: 100 REGISTER
Expires: 150
User-Agent: Grandstream BT110 1.0.8.33
Max-Forwards: 70
Allow: INVITE,ACK,CANCEL,BYE,NOTIFY,REFER,OPTIONS,INFO,SUBSCRIBE
Content-Length: 0

aussie   

Posted at 4:52pm on Wednesday, May 30th, 2007

Well written, easy to follow and very informative.

Keep up your good work!

tejaswi   

Posted at 3:11am on Wednesday, June 13th, 2007

Can i get a simple perl server script DGRAM

Sam,.   

Posted at 5:50am on Thursday, June 21st, 2007

Great article. it helped me a lot to understand the socketing very easily.. thanx a lot..

Sam   

Posted at 2:47am on Friday, June 22nd, 2007

This helped me a lot. could you please post an article like this with forking, threading using socket programming?

Guilherme Arthur   

Posted at 5:17pm on Friday, June 22nd, 2007

Dude!
You saved my life!
XD
Thankx very much!
=D

vijay   

Posted at 12:00am on Sunday, July 1st, 2007

Great article. it helped me a lot to understand the socketing very easily, this is giving the information , how it works well. first of all, if i want to know what is TCP/IP and Perl ( I Understand the functionality of TCP/IP), can any one expalin me from scratch. it will be useful in my QA Career

Anonymous   

Posted at 12:18am on Friday, July 6th, 2007

nice way to do cl-server perl script

anonymous   

Posted at 6:28am on Monday, July 23rd, 2007

nice, this article helped me a lot, keep it up, next one do UDP and maybe find a way to use udp with the quake2 protocol

Smaregow   

Posted at 9:47am on Tuesday, July 24th, 2007

Hi, Can any one help me in solving my questions...my project is some thing like explained below:

My project configuration is something like this...

Clients .Net Message Server Various Servers

TCP/IP is between Clients and .Net message server...and .Net message server is with other servers through COM.

I have 10 clients application and each client has arround few messages...those messages(request) will be send to .Net Message Server which will routes these requests various other Servers and gets the appropriate responses.

By keeping all input messages in the FLAT File I want to Automate the sending and receiving messages using the PERL script and also I want to compare the receving messages aginst the Existing good known results.

My basic questions are....
Is it possible to automate this using PERL script? OR

Do you recomend any other scripting tool to automate this project?

Could any body please help me in taking the right decision?

Many Thanks in Advance,
Smaregow

colin   

Posted at 10:15am on Wednesday, August 1st, 2007

pls give me my tcp/ip to play warlords battlecry

Cat   

Posted at 7:21am on Thursday, August 2nd, 2007

I can has cheezeburger?

Wicked_Sunny   

Posted at 11:29pm on Thursday, August 2nd, 2007

It was really good..
I was really looking for such article to begin with socket programming.

May be I am on my way to develop My Chat application...
Be ready to test my version...

Mihir   

Posted at 1:18am on Saturday, August 11th, 2007

Thanks for this Simple introduction to Perl Sockets to give me a start..

kalyan   

Posted at 2:27am on Saturday, August 18th, 2007

it gud

but describe with starting commands to be used like

intilization of socket,termination of socket e.t.c.

andy   

Posted at 2:12pm on Tuesday, August 21st, 2007

any tips on "after sending the entire request switches to reading until the socket is closed."

I'd love to see this example extended to illustrate this!

matt   

Posted at 4:03pm on Thursday, August 23rd, 2007

I've been stuck on a problem with this regarding the read of the client filehandle...I want a server that periodically goes to check on all it's sockets with clients to see if any of them have messages...if so it'll service the sockets (all the lines of their communication) and then go back to it's normal business. The trick is I dont want to keep opening and closing new sockets and instead just keep them open and read from them when ->select tells me there's stuff there.

What seems to happen however is that my client sends a number of lines of info and the server prints through the first line and then the IO::Select->select then says none of the handles are readable...the can_read returns nothing and so does select. I then wait a bit (like 9 seconds or 3 loops of my "check on the sockets") and send another message from the client...suddenly all the stored up info floods out except again the last line...I then send 5 more lines and it again only writes out the 1st an then says no more...cycle repeating..

Anyway, here's my server code and the client code is beneath it...thanks for any observations!

matt

#!/usr/local/bin/perl


use IO::Socket;
use IO::Select;

my $server_socket = new IO::Socket::INET (
LocalHost => localhost,
LocalPort => 7070,
Proto => 'tcp',
Listen => 32768,
Reuse => 1,
timeout => 5,
);
die "Could not create socket: $!n" unless $server_socket;
print "created socket $server_socketn";

$Read_Handles_Object = new IO::Select(); # create handle set for reading
$Read_Handles_Object->add($server_socket); # add the main socket to the set

while (1) { # forever


while (1) { # keep in this loop as long as there is a readable filehandle..
# get the set of readable handles
#
my ($readable_handles) = IO::Select->select($Read_Handles_Object, undef, undef, 0);

if (! scalar @$readable_handles) {print "nothing left to read...n";last}

foreach $rh (@$readable_handles) {
#print "read handle found : '$rh'n";
# if it is the main socket then we have an incoming connection and
# we should accept() it and then add the new socket to the $Read_Handles_Object
if ($rh == $server_socket) {
# you get this when a new socket connection is formed..a new client starts and it assigns
# a socket filehandle to it.
#print " accept();
$Read_Handles_Object->add($client);
$ClientNumber{$client}=++$CLIENT_COUNT;
#print " %%% Adding '$client' to read setn";
}
# otherwise it is an ordinary socket and we should read and process the request
else {
#print " --this is an ordinary socket '$rh'n";

$buf = $rh->getline(); # grab a line .. it shouldnt block due to the select
if (! defined $buf) {
# the other end of the socket closed...close our end and remove
# it from the list of sockets to listen to..
print " |FROM CLIENT ".$ClientNumber{$rh}."| --socket closed--n";
$Read_Handles_Object->remove($rh);
close($rh);
last;
}
print " |FROM CLIENT ".$ClientNumber{$rh}."|$buf";
}
}
}


# after going through the sockets I'll get back to some other work
# .. I'll simulate that with a sleep 3 ..


print "sleeping...n";
sleep 3;
}



HERES THE CLIENT :

#!/usr/local/bin/perl


use IO::Socket;
my $sock = new IO::Socket::INET ( PeerAddr => 'palm',
PeerPort => '7070',
Proto => 'tcp',
);
die "Could not create socket: $!n" unless $sock;


while(1) {
print "Message : ";
chomp($message=);
print $sock "$messagen";
}

matt   

Posted at 4:04pm on Thursday, August 23rd, 2007

correction...palm on the client is the localhost...adjust that please ... issue still remains...

matt   

Posted at 12:12pm on Friday, August 24th, 2007

it seems that my paste into the entry box stripped out some stuff...like backslash n for a return drops the backslash..watch out for that..also in the client I get stdin with that chomp($message thing but it dropped the "open angle" STDIN "close angle" ...

note that to test this you can up the sleep to like 10 seconds and then while it's sleeping have the client send like 5 strings ... then when the server wakes up it prints out the first and then says no more read handles...then hit return again on the client and out it comes...if you dont like having a sleep this issue would also happen if the server took a few seconds to perform some action for one of the children while another was pumping messages into its socket..
thanks, Matt

baba   

Posted at 5:17am on Tuesday, August 28th, 2007

sorry i couldnt help you at present

shekar   

Posted at 3:42am on Monday, November 12th, 2007

anyone knows how to write smtp mail implementation in PERL , or graphical soket programing to implement SMTP please reply now

Shannon   

Posted at 8:05am on Friday, November 16th, 2007

Anyone can help on the following problem:

(Perl IO::Socket module)The client will prompt the user for two numbers and send them to the server. After server add the numbers and send back to client, THEN client will display the result to the user.

Richard   

Posted at 3:39am on Tuesday, November 20th, 2007

Hi,

The example on top is a one way communication. I would like to send back a message from the serber, to the client:
1) Client sends "Hello there!"
2) Server prints on the screen "Hello there!", and then replies the number of bytes received.
3) Client prints out 12 (the number of bytes sent), and then terminates.

Is there a quick way to do this, or do I have to set up another port for the answer?

Regards,
/Richard

krishna   

Posted at 3:57am on Tuesday, November 27th, 2007

use strict;
use Socket;

# use port 7890 as default
my $port = shift || 7890;
my $proto = getprotobyname('tcp');

# create a socket, make it reusable
socket(SERVER, PF_INET, SOCK_STREAM, $proto) or die "socket: $!";
setsockopt(SERVER, SOL_SOCKET, SO_REUSEADDR, 1) or die "setsock: $!";

# grab a port on this machine
my $paddr = sockaddr_in($port, INADDR_ANY);

# bind to a port, then listen
bind(SERVER, $paddr) or die "bind: $!";
listen(SERVER, SOMAXCONN) or die "listen: $!";
print "SERVER started on port $port n";

# accepting a connection
my $client_addr;
while ($client_addr = accept(CLIENT, SERVER))
{
# find out who connected
my ($client_port, $client_ip) = sockaddr_in($client_addr);
my $client_ipnum = inet_ntoa($client_ip);
my $client_host = gethostbyaddr($client_ip, AF_INET);
# print who has connected
# send them a message, close connection
print CLIENT "Smile from the servern";
print "got a connection from: $client_host"," [$client_ipnum] n";
close CLIENT;}

Pasini   

Posted at 3:29am on Thursday, November 29th, 2007

Hi, I am new to internet programming but I have some years with electronics, microcontrollers and windows apps.
My question is simple and I think PERL may be the right way to solve it. Please help me:
1) I want a socket server and a web/e-mail/ftp server in the same machine, to which I donīt have direct access since it is my ISP machine in another city.
2) How do I create the socket server ? Is it a PERL module and this lines of code from other messages ? How do I install it and how do I run it (I cannot run it from command line !!!) ? Nobody will be able to type commands from command line to run it !
3) The client will be something like hyperterminal from windows (actually an equipment).
Can you suggest a book or tutorial that teaches me how to work with server sockets, install and run it ?
Thanks in advance,
Pasini

Sandy   

Posted at 11:29pm on Tuesday, December 4th, 2007

Very simple and easy to understand..Thanks buddy!

Allen Alex   

Posted at 2:37am on Thursday, December 13th, 2007

GREAT ARTICLE
thanks buddy...

Dale   

Posted at 11:08am on Thursday, December 13th, 2007

This script was a great help! Thanks!

gammy   

Posted at 5:13am on Tuesday, December 18th, 2007

I must say I cannot get this example working at all - I've been tinkering with it for about an hour now and it just doesn't work as explained at all. http://pastebin.ca/821913 shows my code(pretty identical to above)

gammy   

Posted at 8:32am on Tuesday, December 18th, 2007

Ah, I am but a fool! Solved it. Excellent!

james   

Posted at 12:38am on Sunday, December 30th, 2007

Nice article, easy to understand. Thanks!!

Ranjit   

Posted at 11:20am on Friday, January 18th, 2008

How do I incorporate variables into the script above. I got it working, but I am having trouble transferring variables.

Jack   

Posted at 11:56am on Tuesday, January 22nd, 2008

Many thanks. Just a question. How can the server sends a reply to the client?

steve   

Posted at 8:36pm on Tuesday, January 22nd, 2008

excellent... this little bit of code helped me create a simple remote admin script for video switching units with absolutely no previous experience with perl. thanks!

Paras   

Posted at 10:56am on Thursday, January 24th, 2008

Thanks a ton man.. it really helped me in implementing customized script for sending real time logs to central log server (syslog_ng).
Again, thanks a ton for it....

manohar   

Posted at 11:47am on Thursday, February 21st, 2008

can any one suggest with the perl scripts used in automation of SIP testing

Marko   

Posted at 7:29am on Saturday, February 23rd, 2008

Hello,
I am also looking for a perl script to handle SIP testing.

- The idea is to have a simple scrit (ex ua.pl) that sends "template files" as argument (ex: ua.pl template.txt).

- The ua.pl shall sends the data over udp to peer server ip address on port 5060 for instance.

- Template files are not part of the script but written by user .. copy/past from some call flows.

So will be happy if some one post a simple script that reads the file (template) and sends it to server.

ronie   

Posted at 4:58pm on Monday, February 25th, 2008

Hello,
I am new to perl and have been doing some reading. Can someone tell me how to call a script in another host? This article has really helped me, i have been able to create my client and server, but i need to know how to call a sript to do things for me while connecting to the server.
Thanks

Erwin   

Posted at 6:55am on Wednesday, February 27th, 2008

I just implemented the two scripts (server and client) and work fine the first time. While server is runnin in the background I run the client the first time and works, but the second time I run the client I get an error "could not create socket: Connection refuse" then I see the server teminating. Something missing on the code?

harry   

Posted at 2:02pm on Thursday, February 28th, 2008

Erwin, you need to put the $socket->accept() in a loop

Benjamin   

Posted at 1:22am on Tuesday, March 4th, 2008

Hello,

I'm just trying to find a possiblity to check if a specific port (e.g. 80) is listening unter Solaris. But tbh i'm very new to all of that and i thought that active probing (trying to establish a connection to the port, see if it works and cancel the connection if necessary) with a result of 0 or 1 would be best.
I found that article with google but tbh it doesn't help me that much :(

Cheers,
Benjamin

Anonymous   

Posted at 1:10pm on Thursday, March 6th, 2008

Harry,
Thanks, it works as designed. Now I'm looking for a similar client but for Windows, it would be great if done in VBS.
Thanks again.

niks   

Posted at 2:37am on Tuesday, March 25th, 2008

For all those who want to write back something to client, you can use the print statement.

e.g.
1 use IO::Socket;
2 my $sock = new IO::Socket::INET (
3 LocalHost => 'thekla',
4 LocalPort => '7070',
5 Proto => 'tcp',
6 Listen => 1,
7 Reuse => 1,
8 );
9 die "Could not create socket: $!n" unless $sock;
10 my $new_sock = $sock->accept();

At this step you can employ specific code to read something from client and then when its time to write something to client this is what you do:

print $new_sock "Here comes the response from server...n";

Thats it!.

Depending upon the requirement above code may get more complex, but this atleast gives you some idea.

--Niks.

dwight   

Posted at 2:05pm on Monday, March 31st, 2008

Could Anyone Help Me With This Socket Connection?

I'm attempting to tcp a microcontroller. I'm able to do it with vb from a laptop, but I want to communicate from a web page using Perl.

I need to send the characters "F5F0" to the micro controller at ipaddress 24.180.20.119 port 59004. The ipaddress (not real) is to my router and the port is the port of the micro controller. I'm trying this code, it does not reurn an error when udp is used, but returns an internal sever error when I change to tcp:

#!/usr/local/bin/perl -w
use strict;
use IO::Socket::INET;
my $sock = new IO::Socket::INET (
PeerAddr => '24.180.20.119',
PeerPort => '59004',
#Proto => 'tcp',
Proto => 'udp',
);
die "Could not create socket: $!n" unless $sock;
print $sock "F5F0";
close($sock);

print "Content-type: text/htmlnn";
print "Hi there!n";
exit;

The vb program that does work uses winsock like this:

If Winsock1.CtlState MSWinsockLib.StateConstants.sckClosed Then Winsock1.Close()
Winsock1.RemoteHost = IP_Address.Text
Winsock1.RemotePort = 59004
Winsock1.LocalPort = 0
Winsock1.Connect()
If Winsock1.CtlState = MSWinsockLib.StateConstants.sckConnected Then
If RadioButton6.Checked = True Then
Call Winsock1.SendData("F5F0")

endif

Lar   

Posted at 10:07pm on Wednesday, April 16th, 2008

hey everybody, everything looks good and easy, but being a bit defensive minded, can someone point me to resources about checking to make sure we don't get DOS'ed or similar?

Thanks!

Jay   

Posted at 12:04pm on Tuesday, April 22nd, 2008

Thanks a lot, its simple and easy in your demonstration. Great effort mate.

Nhung   

Posted at 6:52am on Wednesday, April 30th, 2008

In the beginning, I used your first program, but it did not work. I dont know why? I installed Apache and Perl on Windows xp? Is that a problem? Do I need to setup something with Perl and Apache to use socket?

bipul   

Posted at 10:23pm on Wednesday, April 30th, 2008

Great Article, well written.
Atleast some basic concepts got cleared.

Comments to date: 53.

Your name:
Your comments:

Security check *

 

Like it? Share it!

  Post to del.icio.us
Post to
del.icio.us
   

Suggested Reading

Perl Cookbook The Perl Cookbook is full of quick solutions to everyday programming problems in perl with explanations and tips easy to understand even for beginners, but also frequently useful even to more experienced programmers. The code is clear and straightforward and the topics covered as well-thought and correspond to real world examples, so frequently you can literally copy code snippets from the book and fit them in your program. It is a nice complement for the Camel Book on your bookshelf.