I have perl client and server. I use IO::Socket to send data between them.
client can send any command to the server, server runs it and send the response back to the client - monitoring like behavior approach.
client.pl stuff:
# !/usr/bin/perl
use 5.022;
use strict;
use warnings;
#tcpclient.pl
use IO::Socket::INET;
my $addr = shift @ARGV;
my $port = shift @ARGV;
# flush after every write
$| = 1;
my ($socket,$client_socket);
# creating object interface of IO::Socket::INET modules which
internally creates
# socket, binds and connects to the TCP server running on the specific
port.
$socket = new IO::Socket::INET (
PeerHost => $addr,
PeerPort => $port,
Proto => 'tcp',
) or die "ERROR in Socket Creation : $!\n";
print "TCP Connection Success.\n";
while (1) {
my $msg = <STDIN>;
$socket->send ($msg);
my $res = <$socket>;
print $res;
}
$socket->close();
server.pl stuff:
# !/usr/bin/perl
use 5.022;
use strict;
use warnings;
#tcpserver.pl
use IO::Socket::INET;
# flush after every write
$| = 1;
my ( $socket, $client_socket );
my ( $peeraddress, $peerport );
# creating object interface of IO::Socket::INET modules which
internally does
# socket creation, binding and listening at the specified port
address.
$socket = new IO::Socket::INET->new(
LocalHost => '0.0.0.0',
LocalPort => '55555',
Proto => 'tcp',
Listen => SOMAXCONN,
Reuse => 1
) or die "ERROR in Socket Creation : $! \n";
print "server waiting for client connection on port 55555\n";
while ( $client_socket = $socket->accept() ) {
# waiting for new client connection.
# get the host and port number of newly connected client.
$peeraddress = $client_socket->peerhost();
$peerport = $client_socket->peerport();
#print "Accepted New Client Connection From : $peeraddress,
$peerport\n ";
while (<$client_socket>) {
print "[$peeraddress $peerport] $_";
my $data = `$_`;
print $data;
$client_socket->send($data);
}
}
$socket->close();
Everything is ok in case the output of the command is one string (commands like uptime, uname, pwd).
If the output contains more strings for e.g. ip a I get only one string on the client side.
I find out that in order to resolve the issue we can use serialization approach. In this way we can use array that can be send from the server side with all strings in it.
I've parsed through StackOverflow and found a lot of such approaches:
How can I send an array in client server program in Perl?
here is the way I tried to change the client and server side in case Storable module usage:
new server.pl stuff with "Storable":
# !/usr/bin/perl
use 5.022;
use strict;
use warnings;
#tcpserver.pl
use IO::Socket::INET;
use Storable qw(nstore_fd);
# flush after every write
$| = 1;
my ( $socket, $client_socket );
my ( $peeraddress, $peerport );
# creating object interface of IO::Socket::INET modules which
internally does
# socket creation, binding and listening at the specified port
address.
$socket = new IO::Socket::INET->new(
LocalHost => '0.0.0.0',
LocalPort => '55555',
Proto => 'tcp',
Listen => SOMAXCONN,
Reuse => 1
) or die "ERROR in Socket Creation : $! \n";
print "server waiting for client connection on port 55555\n";
while ( $client_socket = $socket->accept() ) {
# waiting for new client connection.
# get the host and port number of newly connected client.
$peeraddress = $client_socket->peerhost();
$peerport = $client_socket->peerport();
#print "Accepted New Client Connection From : $peeraddress,
$peerport\n ";
while (<$client_socket>) {
print "[$peeraddress $peerport] $_";
#serialization approach
#save command output in array
my @data = `$_`;
print @data;
#store and send the whole array
nstore_fd( \@data, $client_socket );
}
}
$socket->close();
new client.pl stuff with "Storable":
# !/usr/bin/perl
use 5.022;
use strict;
use warnings;
#tcpclient.pl
use IO::Socket::INET;
use Data::Dumper;
use Storable qw(fd_retrieve);
my $addr = shift @ARGV;
my $port = shift @ARGV;
# flush after every write
$| = 1;
my ($socket,$client_socket);
# creating object interface of IO::Socket::INET modules which
internally creates
# socket, binds and connects to the TCP server running on the
specific port.
$socket = new IO::Socket::INET (
PeerHost => $addr,
PeerPort => $port,
Proto => 'tcp',
) or die "ERROR in Socket Creation : $!\n";
print "TCP Connection Success.\n";
while (1) {
my $msg = <STDIN>;
$socket->send ($msg);
#serialization approach
#retrieve the array
while(my $s = $socket ->accept){
my $struct = fd_retrieve($s);
print Dumper($struct);
}
}
$socket->close();
But the aforementioned did not work for me.
Could someone advise me how my client side can reflect the multiple output from the server side using serialization in the proper way.