perl中数组的序列化用法

Posted

技术标签:

【中文标题】perl中数组的序列化用法【英文标题】:serialization usage for array in perl 【发布时间】:2018-03-02 09:12:19 【问题描述】:

我有 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();

如果命令的输出是一个字符串(uptimeunamepwd 等命令),一切正常。 如果输出包含更多字符串,例如ip a我在客户端只得到一个字符串。

我发现为了解决这个问题,我们可以使用序列化方法。通过这种方式,我们可以使用可以从服务器端发送的数组,其中包含所有字符串。

我通过***进行了解析,发现了很多这样的方法:

How can I send an array in client server program in Perl?

How do I encode a simple array into JSON in Perl?

Perl socket sending hash

这是我尝试更改客户端和服务器端以防Storable模块使用的方式:

带有“可存储”的新 server.pl 内容:

 # !/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 内容:

 # !/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();

但上述对我不起作用。

有人可以告诉我我的客户端如何以正确的方式使用序列化来反映来自服务器端的多个输出。

【问题讨论】:

【参考方案1】:

呼叫accept 是问题所在。摆脱内部while 循环并简单地从套接字读取。在 client.pl 中,您使用 (又名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 支持。将serialisation 升级到Sereal,因为Storable 在不同的Perl 版本之间不兼容。

【讨论】:

啊!太容易了。非常感谢您的帮助。 我玩过代码,发现将 print Dumper($struct) 更改为 ==> print $struct -&gt;[0]; 会产生结果,但不会显示来自 Dumper 的 VAR 和括号,输出更加用户友好。也许对某人有用。

以上是关于perl中数组的序列化用法的主要内容,如果未能解决你的问题,请参考以下文章

perl 多fasta文件匹配,并提取匹配文件第一条序列

js解析与序列化json数据(一)json.stringify()的基本用法

mysql中怎么存储数组?在线等!急!

GGreater and Greater(求满足条件的子序列,bitset用法)

perl处理fasta文件

Perl基础实例---多序列的最长公共子序列LCS