Perl 中的解包功能要求

Posted

技术标签:

【中文标题】Perl 中的解包功能要求【英文标题】:Unpack function requirement in Perl 【发布时间】:2016-01-21 15:45:23 【问题描述】:

我在 Perl 中有一个函数,它以这种方式从模板中读取数据包:

sub read_packet 
  my $contents = shift;
  my @decode = unpack('nnnN', $contents);

  my $version = $decode[0];
  my $identifier = $decode[1];
  my $type = $decode[2];
  my $size = $decode [3];

  @contents = ($version, $identifier, $type, $size);

  return (@contents);

需要对解包函数中的模板进行更改。现在 $identifier 必须支持 32 位,因此根据 PerlMonks:Pack/Unpack Tutorial (aka How the System Stores Data) (N) -> n,N “network”中的 16/32 位值(big- endian) 顺序。

所以这个函数被重写了做这个小改动。现在,发送“数据包”的程序可以发送 16/32 位值。 客户要求我同时支持 16/32 位。如何知道数据包何时包含 16 位或 32 位标识符?

【问题讨论】:

检查数据包的大小? @choroba,我找不到那个文档,pelase,你能给我指点文档吗? 【参考方案1】:

如果这四个字段是数据包包含的全部,那么您可以检查$contents的长度

如果格式为nnnN,则长度为2 + 2 + 2 + 4 = 10 个字节

如果格式为nNnN,则长度为2 + 4 + 2 + 4 = 12字节

但是,如果这四个字段后面有数据,那么您必须尝试最常见的unpack 模板并检查结果是否合理,如果失败则使用替代模板

【讨论】:

【参考方案2】:

当协议以不兼容的方式更改时,版本也应该更改。如果是这样,您可以使用以下内容:

sub read_packet 
  my $contents = shift;
  (my $version, $contents) = unpack('na*', $contents);

  if ($version < X) 
     return ( $version, unpack('nnN', $rest) );
   else 
     return ( $version, unpack('NnN', $rest) );
  

否则,您将根据数据包的大小来确定它。但是,这需要传输数据包的大小,但并非总是如此。幸运的是,这里似乎确实如此,因此您可以使用以下内容:

sub read_packet 
  my $contents = shift;
  return unpack(length($contents) < 12 ? 'nnnN' : 'nNnN', $contents);

【讨论】:

以上是关于Perl 中的解包功能要求的主要内容,如果未能解决你的问题,请参考以下文章

“W”在 Perl 的解包函数中究竟做了啥?

python中的解包

Python中的解包用法

ToolsRDB打包工具详解

ToolsRDB打包工具详解

熊猫数据框python中的解包列表[重复]