我正在尝试完成一个需要从套接字读取 4 个无符号整数的小型 Perl 学习项目。我无法读取超过 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);
具体问题:
任何帮助,指针等表示赞赏。顺便说一句,“学习项目”是 overthewire.org - 非常酷的东西。
最佳答案
你的socket是TCP还是UDP?recv
是比 <>
低级的例程/readline
.它或多或少直接映射到 recv(2)
系统调用。如果套接字数据作为 4 个 4 字节的数据包到达,recv
即使已经提供了更大的缓冲区,它也会在看到第一个数据包后立即返回。如果所有 4 个数据包在第一次调用 recv()
之前到达,那么您是否获得所有数据或仅获得一份数据可能取决于它是 TCP 还是 UDP。
如果您使用的是 TCP,则数据包可能会在传输过程中被分段。 16 字节的有效负载不太可能发生这种情况,但最佳实践是不要假设 16 字节的数据会一次全部显示出来,即使您知道服务器一次发送了所有数据。网络应用程序通常需要缓冲传入的数据,或者,您可以通过使用 $/ = \16
指定 16 字节记录来让 perl 为您做这件事。 .
另一种可能性,我发现它比 <>
更自然对于这种 I/O 用法,是使用 read
或 sysread
函数(或 OO 等价物,在 IO::Socket
父类(super class) IO::Handle
中定义)。那些需要一个长度参数,但和以前一样,你不应该假设整个缓冲区会被一次填满。
关于perl - socket->recv() 与 <>?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5599585/