socket-> recv()vs. <>?

111*_*110 6 sockets perl recv

我正在尝试通过一个小的Perl学习项目,该项目需要从套接字中读取4个无符号整数.我无法获得超过1个整数读取,并在挖掘后找到了解决方案.但我需要了解我做得不对(并且经历过几本Perl书籍,perldocs等等都无济于事.)

示例1:这是成功的解决方案代码(原始),假设下面的套接字连接成功:

{
  local $/ = \16; # make <> read in 16 bytes with one swoop.
  my @integers = unpack "IIII", <$sock>;
  print "numbers: @val\n";
}
Run Code Online (Sandbox Code Playgroud)

例2:我在下面尝试过这个.如果我在解压缩之前打印输入,我只得到一个整数:

my $input;
$sock->recv($input,16,0);
my @integers = unpack("IIII", $input);
Run Code Online (Sandbox Code Playgroud)

具体问题:

  1. 在例1中,什么是"$ /"?它是如何"改变"<>,我认为这是STDIN?
  2. 在示例2中,为什么我的recv()不会从套接字中取出多于一个整数?我的理解(per perldoc)是"SIZE"参数默认为"bytes",整数是4个字节?

任何帮助,指针等都表示赞赏.顺便说一下,"学习项目"是一个非常酷的东西.

And*_*ndy 5

您的套接字是TCP还是UDP?

recv是比<>/ 低的例程readline。它或多或少直接映射到recv(2)系统调用。如果套接字数据以4个4字节的数据包的形式到达,recv即使看到了第一个数据包,它也会立即返回,即使它已被提供了更大的缓冲区。如果所有4个数据包在第一次调用之前到达recv(),那么是否要获取所有数据还是仅获取一个数据,可能取决于它是TCP还是UDP。

如果您使用的是TCP,则数据包可能会在传输中被分段。对于16字节的有效负载,这种情况不太可能发生,但是最佳实践是不要假定即使您知道服务器一次发送所有数据,也无法一次显示全部16字节的数据。通常期望网络应用程序缓冲传入的数据,或者,您可以通过使用指定16字节记录来让perl为您完成$/ = \16

我发现比<>这种I / O用法更自然的另一种可能性是使用reador sysread函数(或OO等效项,它们在IO::Socket超类中定义IO::Handle)。它们带有一个长度参数,但是像以前一样,您不应假定整个缓冲区都将被立即填充。


Dal*_*aen 2

至于1)

好吧,<>接受任何文件句柄,包括套接字。按照惯例您可以将其留空,在这种情况下,会假定某种合理的默认行为。请参阅perldoc perlop(在里面搜索<>)。

特殊变量$/是记录分隔符,默认为“\n”。您可以取消定义它并立即读取整个文件(这称为 slurping)。perldoc perlvar更多内容请参见(\number案例也在那里)。