socket-> recv()vs.<>?

时间:2011-04-08 18:56:57

标签: perl sockets recv

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

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

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

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

my $input;
$sock->recv($input,16,0);
my @integers = unpack("IIII", $input);

具体问题:

  1. 在示例1中,什么是“$ /”?它是如何“改变”&lt;&gt;,我认为这是STDIN?
  2. 在示例2中,为什么我的recv()不会从套接字中取出多于一个整数?我的理解(per perldoc)是“SIZE”参数默认为“bytes”,整数是4个字节?
  3. 任何帮助,指示等都表示赞赏。顺便说一下,“学习项目”是一个非常酷的东西。

3 个答案:

答案 0 :(得分:4)

您的套接字是TCP还是UDP?

recv是比<> / readline更低级的例行程序。它或多或少直接映射到recv(2)系统调用。如果套接字数据作为4个4字节数据包到达,recv将在看到第一个数据包后立即返回,即使它已被提供更大的缓冲区。如果所有4个数据包在第一次调用recv()之前到达,那么您是获得所有数据还是只获得一个数据可能取决于它是TCP还是UDP。

如果您使用TCP,则数据包可能会在飞行中碎片化。 16字节有效载荷不太可能发生,但最佳做法是不假设即使您知道服务器一次性发送所有数据,也会立即显示16字节的数据。网络应用程序通常需要缓冲传入的数据,或者,您可以通过使用$/ = \16指定16字节的记录来为您执行此操作。

对于这种I / O使用,我觉得比<>更自然的另一种可能性是使用readsysread函数(或OO等价物,它们是在IO::Socket超类IO::Handle中定义。那些采用长度参数,但和以前一样,你不应该假设整个缓冲区将被立即填充。

答案 1 :(得分:1)

至于1)

好吧,<>采用任何文件句柄,包括套接字。你可以将它留空,这是约定,在这种情况下,假定某种理智的默认行为。请参阅perldoc perlop(在里面搜索<>)。

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

答案 2 :(得分:1)

readreadline(又名<>)等待请求的字符数量在返回之前可用。它只会在出现错误或EOF时返回更少的字符,在这种情况下,下一次读取将返回错误或EOF。

只要有一些字符可用,

sysread就会返回,即使数量少于请求的数量。

根据您的说法,recv就像sysread。如果您需要16个字符,则必须循环,直到您有16个字符或使用readreadline