REQUIREMENTS:
The s.erver waits for connection.
Once the client runs, the connection through the socket is developed successfully.
The Server reads a text file and sends the message to the Client.
The Client listens to it and prints it.
The Client reads a text file sends the message (acknowledgement) to the Server.
The Server listens to it and prints it.
Here is the solution to the above mentioned problem:
SERVER SCRIPT:
#!/usr/bin/perl
use strict;
use warnings;
use IO::Socket::INET;
my $socket;
my $clientsocket;
my $serverdata;
my $clientdata;
$socket = new IO::Socket::INET (
LocalHost => '127.0.0.1',
LocalPort => '0155',
Proto => 'tcp',
Listen => 1,
Reuse => 1
) or die "Oops: $! \n";
print "Waiting for the Client.\n";
$clientsocket = $socket->accept();
print "Connected from : ", $clientsocket->peerhost(); # Display messages
print ", Port : ", $clientsocket->peerport(), "\n";
# Write some data to the client
$serverdata = "This is the Server speaking :)\n";
print $clientsocket "$serverdata \n";
# read the data from the client
$clientdata = <$clientsocket>;
print "Message received from Client : $clientdata\n";
$socket->close();
CLIENT SCRIPT:
#!/usr/bin/perl
use strict;
use warnings;
use IO::Socket::INET;
my $socket;
my $serverdata;
my $clientdata;
$socket = new IO::Socket::INET (
PeerHost => '127.0.0.1',
PeerPort => '0155',
Proto => 'tcp',
) or die "$!\n";
print "Connected to the Server.\n";
# read the message sent by server.
$serverdata = <$socket>;
print "Message from Server : $serverdata \n";
# Send some message to server.
$clientdata = "This is the Client speaking :)";
print $socket "$clientdata \n";
$socket->close();
Related
I'm writing a simple TCP client and server Perl script.
As of now I verify the 3 way TCP handshake using wireshark, and the connection is established.
But when i try to send or recv data nothing happens.
Questions:
1) the major difference between the client and the server is only that the server has an added LISTEN parameter which enables it to listen for incoming connections ?
2)Are there any steps missing between recv and displaying the data?
3)Shouldn't atleast the hardcoded string "$response" be sent when the program executes the while loop the first time?
4)How do shutdown($sock,1) and sleep(1) differ in this implementation? Is it okay to let the socket sleep or should I use shutdown($sock,1) to signal to the client/server that data has been sent ?
on inspecting the status of the connection in wireshark, i've noticed that only the handshake takes place. there is no data exchanged at all. So im pretty sure the problem lies somewhere on writing to the socket and reading data from the socket (using the keyboard or hardcoded strings).
Any help would be really appreciated.
The client is as follows:
#!/usr/bin/perl
use IO::Socket;
use Getopt::Long;
#$IP_addr = $ARGV[0];
#$tgt_port = $ARG[1];
#netcat client
$port = 9040;
$sock = IO::Socket::INET->new( PeerAddr => 'localhost',
PeerPort => $port,
LocalPort => 9000,
Proto => 'tcp')
or die "\nunable to bind on localhost : $port...";
while ($sock){
#Get the clients IP and port number
$client_IP = $sock -> peerhost();
#$client_IP = 'localhost';
$client_port = $sock -> peerport();
print "\n Connected to $client_IP $client_port \n";
#Reading from socket
$data;
$sock ->recv($data, 1024);
print $data;
#writing to socket
$sock->autoflush(1);
$response = "response: OK recvd\n" ;
$sock->send($response);
shutdown($sock,1);
}
$sock -> close();
The server is as follows:
#!/usr/bin/perl
use IO::Socket;
use Getopt::Long;
#$IP_addr = $ARGV[0];
#$tgt_port = $ARG[1];
#netcat server
$port = 9040;
$sock = IO::Socket::INET->new( Listen => 1,
LocalAddr => 'localhost',
LocalPort => $port,
Proto => 'tcp')
or die "\nunable to bind on localhost : $port...";
while ($sock){
print "\nListening on port $port ...\n";
$sock = $sock -> accept();
#Get the clients IP and port number
$client_IP = $sock->peerhost();
$client_port = $sock->peerport();
print "\n Connected from $client_IP $client_port \n";
#Reading from socket
$data ->recv($sock, 1024);
print $data;
#writing to socket
$sock->autoflush(1);
$response = "oohlalala" ;
$sock -> send($response);
shutdown($sock, 1);
}
$sock -> close();
From IO::Socket:
As of VERSION 1.18 all IO::Socket objects have autoflush turned on by
default. This was not the case with earlier releases.
Perl version 2.0 was released in 1988. You are most likely using perl version 5.x.
1) the major difference between the client and the server is only that
the server has an added LISTEN parameter which enables it to listen
for incoming connections ?
According to the docs:
If Listen is defined then a listen socket is created...
A listen socket can call accept(). If a regular socket calls accept(), accept() returns undef.
accept()
In a scalar context the new socket is returned, or undef upon failure.
In a list context a two-element array is returned containing the new
socket and the peer address; the list will be empty upon failure.
https://perldoc.perl.org/IO/Socket.html
Here is a nice, short, basic description of sockets.
Your server code probably hides some of what's going on. It would be more illustrative if it was written like this:
$server_socket = IO::Socket::INET(.....);
...
...
my $client_socket = $server_socket->accept();
...
...
There are two different sockets. accept() returns a new socket for the server and the client to communicate with, so the original server socket can keep listening for client connections.
2) Are there any steps missing between recv and displaying the data?
Depending on what you're doing, you might want to get rid of the characters that mark the end of the data, which the code would have used to signal the other side that it should stop trying to read more data from the socket.
Receiving the data is the tricky part. An agreed upon protocol must be used by both the client and the server to avoid deadlock, which is when both the client and the server are waiting for the other side to send data. In the example below, I employ a "line oriented" protocol where one side stops reading from the socket when it reads a newline. In networking, by convention a newline is considered to be "\r\n", which represents the ascii characters carriage return and line feed, but to avoid any type of automatic "\n" translations on various OS's, the socket library uses the actual ascii codes: 13 and 10, which in hex notation is: "\x0D\x0A".
server.pl:
use strict;
use warnings;
use 5.020;
use autodie;
use Data::Dumper;
use IO::Socket::INET;
use Socket qw( :crlf ); # "\x0D\x0A" constants CRLF and $CRLF
my $host = 'localhost';
my $port = 15_678;
my $server_socket = IO::Socket::INET->new(
Listen => 5,
LocalPort => $port,
LocalAddr => $host,
Proto => 'tcp',
ReuseAddr => 1,
ReusePort => 1
);
say "Server listening on port: $port\n";
while (my $client_socket = $server_socket->accept() ) {
my $client_ip = $client_socket->peerhost();
my $client_port = $client_socket->peerport();
say "Connection from $client_ip:$client_port";
{
local $/ = CRLF; # $/ is the input record separator, which is "\n"
#by default. Both <$INFILE> and getline() read up to
#and including the input record separator.
while(my $line = $client_socket->getline) { #Blocks until CRLF is read
#from the socket or the other
#side closes the socket.
chomp $line; #chomp() removes input record separator from end of line.
say "Server received: $line";
my $response = reverse $line;
$client_socket->send("$response$CRLF");
say "Server sent: $response";
}
} #Here $/ is restored to whatever it was before this parenthesized block.
#That is what declaring a variable as local does.
say "-" x 30;
#Execution arrives here after the client closes the socket:
$client_socket->shutdown(2); #Send signals to other side of socket.
#Not necessary in this example because other threads
#aren't also reading from the socket.
$client_socket->close(); #Close the filehandle associated with the socket.
}
Note that just like when reading a file, getline will return everything it has read so far when it receives an eof signal, and for the next iteration of the while loop getline will return undef causing the while loop to terminate.
client.pl:
use strict;
use warnings;
use 5.020;
use autodie;
use Data::Dumper;
use IO::Socket::INET;
use Socket qw( :crlf ); #\x0D\x0A constants CRLF and $CRLF
my $port = 15_678;
my #lines = (
"hello world",
"goodbye mars",
);
my $sock = IO::Socket::INET->new("localhost:$port");
for my $line(#lines){
my $server_ip = $sock->peerhost();
my $server_port = $sock->peerport();
say "Connected to $server_ip:$server_port";
$sock->send("$line$CRLF");
say "Client sent: $line";
my $response;
{
local $/ = CRLF;
$response = $sock->getline();
chomp $response;
}
say "Client received: $response";
say '-' x 30;
}
#Tell the server that no more data is coming from this client:
$sock->shutdown(2); #Send signals to other side of socket.
$sock->close(); #Close the filehandle associated with the socket.
After running the client program twice...
Server output:
Server listening on port: 15678
Connection from 127.0.0.1:56085
Server received: hello world
Server sent: dlrow olleh
Server received: goodbye mars
Server sent: sram eybdoog
------------------------------
Connection from 127.0.0.1:56096
Server received: hello world
Server sent: dlrow olleh
Server received: goodbye mars
Server sent: sram eybdoog
------------------------------
Client output:
$ perl client.pl
Connected to 127.0.0.1:15678
Client sent: hello world
Client received: dlrow olleh
------------------------------
Connected to 127.0.0.1:15678
Client sent: goodbye mars
Client received: sram eybdoog
------------------------------
$ perl client.pl
Connected to 127.0.0.1:15678
Client sent: hello world
Client received: dlrow olleh
------------------------------
Connected to 127.0.0.1:15678
Client sent: goodbye mars
Client received: sram eybdoog
------------------------------
$
3) Shouldn't atleast the hardcoded string "$response" be sent when the
program executes the while loop the first time?
Yes, all statements in a while loop will have executed after the first loop has finished executing--but when a statement higher up in the loop is blocking, then the send will never execute.
4) How do shutdown($sock,1) and sleep(1) differ in this implementation? Is it okay to let the socket sleep or should I use
shutdown($sock,1) to signal to the client/server that data has been
sent ?
I'm not sure how shutdown() and sleep() are related in any way. sleep() stops your code from executing for the specified time, while shutdown() sends something to the other side of a socket.
"Closing the socket", i.e. calling shutdown(), to mark the end of the data is another protocol that you can adopt. It makes things pretty easy: one side just continues to read from the socket in some sort of read statement, and when the other side closes the socket, the read will return. Here's an example:
server.pl:
use strict;
use warnings;
use 5.020;
use autodie;
use Data::Dumper;
use IO::Socket::INET;
my $host = 'localhost';
my $port = 15_678;
my $server_socket = IO::Socket::INET->new(
Listen => 5,
LocalPort => $port,
LocalAddr => $host,
Proto => 'tcp',
ReuseAddr => 1,
ReusePort => 1
);
say "Server listening on port: $port\n";
while (my $client_socket = $server_socket->accept() ) {
my $client_ip = $client_socket->peerhost();
my $client_port = $client_socket->peerport();
say "Connection from $client_ip:$client_port";
my $data;
{
local $/ = undef; #This input record separtor will never be found...
$data = <$client_socket>; #...so this reads everything--including newlines--until it gets an eof signal.
}
say "Server received: $data";
my $response = reverse $data;
$client_socket->send($response);
$client_socket->shutdown(2); #Doesn't close filehandle -- merely sends signals.
$client_socket->close(); ##Close the filehandle associated with the socket.
say "Server sent: $response";
say "-" x 30;
}
client.pl:
use strict;
use warnings;
use 5.020;
use autodie;
use Data::Dumper;
use IO::Socket::INET;
my $port = 15_678;
my #data = (
"hello \n world", #Now newlines are in the data
"goodbye \n mars",
);
for my $data (#data){
my $sock = IO::Socket::INET->new("localhost:$port");
my $server_ip = $sock->peerhost();
my $server_port = $sock->peerport();
say "Connected to $server_ip:$server_port";
$sock->send($data);
say "Client sent: $data";
$sock->shutdown(1);
my $response;
{
local $/ = undef; #This input record separtor will never be found...
$response = <$sock>; ##...so this reads everything--including newlines--until it gets an eof signal.
}
$sock->shutdown(0);
$sock->close();
say "Client received: $response";
say '-' x 30;
}
Server output:
Server listening on port: 15678
Connection from 127.0.0.1:53139
Server received: hello
world
Server sent: dlrow
olleh
------------------------------
Connection from 127.0.0.1:53140
Server received: goodbye
mars
Server sent: sram
eybdoog
------------------------------
Client output:
Connected to 127.0.0.1:15678
Client sent: hello
world
Client received: dlrow
olleh
------------------------------
Connected to 127.0.0.1:15678
Client sent: goodbye
mars
Client received: sram
eybdoog
------------------------------
Code for the server (tested with telnet localhost 9040):
use strict;
use warnings;
use IO::Socket::INET;
my $port = 9040;
my $listen = IO::Socket::INET->new(Listen => 1,
LocalPort => $port,
Proto => 'tcp',
ReuseAddr => 1,
ReusePort => 1);
while ($listen) {
print "\nListening on port $port ...\n";
my $sock = $listen->accept();
my $client_IP = $sock->peerhost();
my $client_port = $sock->peerport();
print "\n Connected from $client_IP $client_port \n";
my $data;
$sock->recv($data, 1024);
print $data;
#writing to socket
$sock->autoflush(1);
my $response = "oohlalala\n" ;
$sock->send($response);
shutdown($sock, 1);
}
Client code (tested against above server):
use strict;
use warnings;
use IO::Socket::INET;
my $port = 9040;
my $sock = IO::Socket::INET->new(PeerAddr => 'localhost',
PeerPort => $port,
Proto => 'tcp');
if ($sock) {
my $server_IP = $sock->peerhost();
my $server_port = $sock->peerport();
print "\n Connected to $server_IP $server_port \n";
# initiate protocol
$sock->autoflush(1);
print $sock "OK\n";
my $data;
$sock->recv($data, 1024);
print $data;
shutdown($sock, 1);
}
Output from server:
Listening on port 9040 ...
Connected from 127.0.0.1 36106
OK
Listening on port 9040 ...
Output from client:
Connected to 127.0.0.1 9040
oohlalala
My Procedure: i am opening a file "output.txt , readin gits last line which will have the String "PASS" or "FAIL" , if PASS if found then i want to send string "OK" to server else i have to send string "ERROR"
Issue Observed: I am not able to recieve anything on Remote Server(IP 10.5.62.1) but if try using Localhost (IP 127.0.0.1) , i am able receive the string from the client. Please help to receive the string on the remote server.
I am getting the following error
:send: Cannot determine peer address at C:\client.pl line 44
IO::Socket::send('IO::Socket::INET=GLOB(0x31cc20)', 'ERROR') called at
C:\client.pl line 44
client code :
#standard includes
use strict;
use warnings;
use diagnostics;
use IO::Socket::INET;
use IO::File;
use English;
#local variables
my $Socket;
#Create Socket for a specified port number
$Socket = new IO::Socket::INET (
PeerAddr => '10.5.62.1',
PeerPort => '4754',
Proto => 'tcp',
Listen => 1,
);
die "Could not create socket: $!\n" unless $Socket;
#open the file which is required , mapping file to INPUT Macro
open INPUT, "<output.txt";
#Reading all lines from a file and storing in #lines array
my #lines = <INPUT>;
close INPUT;
#Now #lines holds all the lines, one line in each element.
print "Last line is:\n";
#checking the last line in the file as it will have the verdict "Pass" or "Fail"
print $lines[-1];
if($lines[-1]=~ 'Pass')
{
print "Setting verdict PASS and sending OK";
#Sending Ok to Server on Ping Success
# print $Socket "\r\nOK\r\n";
$Socket->send("\r\nOK\r\n");
}
else
{
print "Setting verdict FAIL and sending ERROR";
#Sending ERROR to Server on failure
# print $Socket "\r\nERROR\r\n";
$Socket->send("ERROR");
}
#Now closing the socket as my job is done
close($Socket);
Server Code:
use IO::Socket;
my $sock = new IO::Socket::INET (
LocalHost => '10.5.62.1',
LocalPort => '4754',
Proto => 'tcp',
Listen => 1,
Reuse => 1,
);
die "Could not create socket: $!\n" unless $sock;
my $new_sock = $sock->accept();
while(<$new_sock>) {
print $_;
}
close($sock);
I am a beginner to Perl socket programming. As of now, the server sends a string and the client responds with another string in my program. Later, if the server sends another string, the client is not able to receive it. To transfer data between the server and client for multiple times, should I include any functions?
SERVER:
#!/usr/bin/perl
use strict;
use warnings;
use IO::Socket::INET;
my $socket;
my $clientsocket;
my $serverdata;
my $clientdata;
$socket = new IO::Socket::INET (
LocalHost => '127.0.0.1',
LocalPort => 2500,
Proto => 'tcp',
Listen => 1,
Reuse => 1
) or die "Oops: $! \n";
print "Waiting for the Client.\n";
$clientsocket = $socket->accept();
print "Connected from : ", $clientsocket->peerhost();
print ", Port : ", $clientsocket->peerport(), "\n";
# Write some data to the client
$serverdata = "This is the Server speaking \n";
print $clientsocket "$serverdata \n";
# read the data from the client
$clientdata = <$clientsocket>;
print "$clientdata";
$serverdata = "Server Again writing \n";
print $clientsocket "$serverdata";
$socket->close();
CLIENT:
#!/usr/bin/perl
use strict;
use warnings;
use IO::Socket::INET;
use Tk;
my $socket;
my $serverdata;
$socket = new IO::Socket::INET (
PeerHost => '127.0.0.1',
PeerPort => '2500',
Proto => 'tcp',
) or die "$!\n";
print "Connected to the Server.\n";
# read the message sent by server.
$serverdata = <$socket>;
print "Message from Server : $serverdata \n";
# Send some message to server.
my $name = "Client here!";
print $socket "$name";
# Read message sent by server.
$serverdata = <$socket>;
print "$serverdata";
$socket->close();
Printing of $serverdata second time in the Client side is not happening.
If you use to read message from another end, the sender must end the message with "\n".
Alternatively, you can use recv(...) so the message won't be buffered till newline character.
Just make sure your client sends a whole line. SInce you are reading with
<$clientsocket>
your server waits for a "\n" from the client.
Your server starts listening on some port. It waits until a client connects, the accepts that connection. It reads and writes a bit of data over the client connection. And then? Then it just closes the socket and exits the program.
That is not what you intended: You want the server to start waiting for the next connection. That means some kind of loop: Each time a client connects, we'll do our communication:
while (my $client = $socket->accept) {
# do something with the $client
}
I recommend you read through the relevant sections of perldoc perlipc, but keep in mind it uses outdated best practices, so don't directly copy anything.
I have created an HTTP server in Perl to accept requests from clients.
At the moment only one client is sending the request.
This is how my set-up is:
Client --> Server (this is proxy server as well connecting to the internet), Apache 2 running on Ubuntu.
This is the Perl code for my server:
#!/usr/bin/perl
use IO::Socket::INET;
use strict;
use warnings;
use LWP::Simple;
# auto-flush on socket
$| = 1;
my $port = 7890;
# Create a listening port
my $socket = new IO::Socket::INET(
LocalHost => '127.0.0.1',
LocalPort => shift || $port,
Proto => 'tcp',
Listen => SOMAXCONN,
Reuse => 1
) or die "cannot create socket $!\n";
# open a file and write client requests to the file
$| = 1;
open(FH, '>>', '/home/suresh/clientrequest.txt')
or die "could not open the /home/suresh/clientrequest : $!\n";
print FH "server waiting for client on port\n"
or die "could not write to file : $!\n";
while (my $client_socket = $socket->accept()) {
$client_socket->autoflush(1);
#print FH "Welcome to $0 \n";
my $client_address = $socket->peerhost();
my $client_port = $client_socket->peerport();
print FH "connection from $client_address:$client_port\n";
# read from connected client
my $data = "";
$client_socket->recv($data, 1024);
print FH "Data received from $client_address:$client_port: $data\n";
# write response data to the client
$data = "Sucessfully processed your request";
$client_socket->send($data);
shutdown($client_socket, 1);
}
close(FH);
$socket->close();
When I bring this server up and try sending a request from a client, the request is written to the file, so it looks like the requests are captured by the server.
Can anyone please let me know what other configurations I need to do at server side and at client?
If you write
$| = 1;
then flushing is only activated for the default output filehandle. This is STDOUT unless changed with the select() builtin. So FH is not flushed here — I guess this was your intention. Instead, you have to write
FH->autoflush(1);
I'm trying to create a chat server using sockets in Perl. However, when I run the Server program I get the error:
"ERROR:(9)(Bad file descriptor)(6)(+The handle is invalid) at Server.pl line 21."
and when I run the client program I get the error:
"Cannot create the socket: No connection could be made because the target machine
actively refused it."
Here is the Server program:
#!usr/bin/perl
#server.pl
use IO::Socket;
$| = 1;
print "Server Program\n";
my $lp = 12000;
my $server_socket, $new_client, $addr, $port;
$server_socket = new IO::Socket::INET (
LocalHost => '127.0.0.1',
LocalPort => $lp,
Proto => 'tcp',
Reuse => 1) or die "Cannot create the socket: $!\n";
print "Server started at port $lp \n";
while (1) {
$new_client = $server_socket->accept() or die sprintf "ERROR:(%d)(%s)(%d)(+%s)", $!,$!,$^E,$^E;
$addr = $new_client->peerhost();
$port = $new_client->peerport();
print "Connected to client at $addr at port $port ";
while(<$new_client>) {
print "Following is the text entered by client: \n";
print "$_";
}
print "Client now disconnecting..\n";
close $new_client;
}
$server_socker->close();
And here is the client:
#!usr/bin/perl
#client.pl
use IO::Socket;
$| = 1;
print "Client Program\n";
my $lp = 12000;
my $client_socket = new IO::Socket::INET (
PeerHost => '127.0.0.1',
PeerPort => $lp,
Proto => 'tcp',
Reuse => 1) or die "Cannot create the socket: $!\n";
print "Server connected at port $lp \n";
print "Enter the text to sent to the server: \n";
$user_input = <>;
chomp $user_input;
print $plient_socket;
$client_socket->send($user_input);
$client_socket->close();
I am new to this and I'm not getting where I'm going wrong. Could anybody help?
You trying to accept a connection from a socket that's not listening. Add
Listen => SOMAXCONN,
And now for off-topic comments about your code:
Always use use strict; use warnings;. It will highlight some other problems with your code.
It doesn't make any sense to relative paths on the shebang line. You're missing a /.
On the style front, it's considered bad form to declare variables ahead of where they are used. The whole point of declaring variables is to limit their scope, so declaring them at the top of the program defies the purpose.
LocalHost => '127.0.0.1' (better written as LocalHost => INADDR_LOOPBACK) makes it so you can only receive connections from 127.0.0.1. That can be useful, but I don't know if you did that intentionally. The default, INADDR_ANY, allows connections from any interface.