我正在尝试通过一个小的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);
具体问题:
任何帮助,指示等都表示赞赏。顺便说一下,“学习项目”是一个非常酷的东西。
答案 0 :(得分:4)
您的套接字是TCP还是UDP?
recv
是比<>
/ readline
更低级的例行程序。它或多或少直接映射到recv(2)
系统调用。如果套接字数据作为4个4字节数据包到达,recv
将在看到第一个数据包后立即返回,即使它已被提供更大的缓冲区。如果所有4个数据包在第一次调用recv()
之前到达,那么您是获得所有数据还是只获得一个数据可能取决于它是TCP还是UDP。
如果您使用TCP,则数据包可能会在飞行中碎片化。 16字节有效载荷不太可能发生,但最佳做法是不假设即使您知道服务器一次性发送所有数据,也会立即显示16字节的数据。网络应用程序通常需要缓冲传入的数据,或者,您可以通过使用$/ = \16
指定16字节的记录来为您执行此操作。
对于这种I / O使用,我觉得比<>
更自然的另一种可能性是使用read
或sysread
函数(或OO等价物,它们是在IO::Socket
超类IO::Handle
中定义。那些采用长度参数,但和以前一样,你不应该假设整个缓冲区将被立即填充。
答案 1 :(得分:1)
至于1)
好吧,<>
采用任何文件句柄,包括套接字。你可以将它留空,这是约定,在这种情况下,假定某种理智的默认行为。请参阅perldoc perlop
(在里面搜索<>
)。
特殊变量$/
是记录分隔符,默认为“\ n”。您可以取消它并立即读取整个文件(这称为slurping)。有关详情,请参阅perldoc perlvar
(\number
案例也在那里)。
答案 2 :(得分:1)
read
和readline
(又名<>
)等待请求的字符数量在返回之前可用。它只会在出现错误或EOF时返回更少的字符,在这种情况下,下一次读取将返回错误或EOF。
sysread
就会返回,即使数量少于请求的数量。
根据您的说法,recv
就像sysread
。如果您需要16个字符,则必须循环,直到您有16个字符或使用read
或readline
。