我有perl客户端和服务器。我使用IO :: Socket在它们之间发送数据。
客户端可以向服务器发送任何命令,服务器运行它并将响应发送回客户端 - 监视行为方法。
client.pl的东西:
# !/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的东西:
# !/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();
如果命令的输出是一个字符串(命令如uptime
,uname
,pwd
),一切都可以。如果输出包含更多字符串,例如ip a
我在客户端只得到一个字符串。
我发现为了解决这个问题,我们可以使用序列化方法。通过这种方式,我们可以使用可以从服务器端发送的数组,其中包含所有字符串。
我已经通过StackOverflow进行了解析,发现了很多这样的方法:
How can I send an array in client server program in Perl?
这是我尝试更改客户端和服务器端的方式,以防Storable
模块使用:
新的server.pl与“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();
新的client.pl“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();
但前面提到的并不适用于我。
有人可以告诉我,我的客户端如何能够以正确的方式使用序列化来反映服务器端的多个输出。
打电话给accept
是个问题。摆脱内部while
循环,只需从套接字读取。在client.pl中,您使用<>(a.k.a。readline)运算符执行此操作,在new_client.pl中,fd_retrieve
将隐式为您执行此操作。
while (1) {
my $msg = <STDIN>;
$socket->send($msg);
my $struct = fd_retrieve($socket);
print Dumper($struct);
}
PS:升级到IO::Socket::IP,以便获得IPv6支持。升级到Sereal以获取serialisation,因为Storable与不同的Perl版本不兼容。