gpt4 book ai didi

perl - Perl中的套接字编程,Perlio层有问题吗?

转载 作者:行者123 更新时间:2023-12-03 11:56:28 25 4
gpt4 key购买 nike

我注意到perl中的perlio层存在一些问题。让我度过了美好的一天来追踪它,希望其他人对此有所了解?最为可怕的是,由于其级别如此之低,我担心它会降低代码的可移植性。

服务器代码:

use strict;
use Socket;

socket(my $sock, AF_INET, SOCK_STREAM, getprotobyname('tcp')) or die();
setsockopt($sock, SOL_SOCKET, SO_REUSEADDR, 1) or die();
bind($sock, pack_sockaddr_in(23457, inet_aton('0.0.0.0'))) or die();
listen($sock, 10) or die();

my $paddr = accept(my $csock, $sock);
if (not $paddr) {
die();
}
my ($port, $iaddr) = unpack_sockaddr_in($paddr);
printf "accepted %s:%s\n", inet_ntoa($iaddr), $port;
send($csock, "1234567890", 0);
recv($csock, my $tmp, 8192, 0);
close($csock);
close($sock);

客户端代码(我稍作更改以进行测试):
use strict;
use Socket;
use PerlIO;

socket(my $sock, AF_INET, SOCK_STREAM, getprotobyname('tcp')) or die();
connect($sock, pack_sockaddr_in(23457, inet_aton('localhost'))) or die();
print "layers before = ".join(', ', PerlIO::get_layers($sock))."\n";
#binmode($sock, ':pop'); # uncomment this line to watch the code work...
print "layers after = ".join(', ', PerlIO::get_layers($sock))."\n";

my $tmp;
print "1ret = ".read($sock, $tmp, 1)."\n"; print "tmp $tmp\n"; stillpending($sock);
print "1ret = ".read($sock, $tmp, 1)."\n"; print "tmp $tmp\n"; stillpending($sock);
print "1ret = ".read($sock, $tmp, 1)."\n"; print "tmp $tmp\n"; stillpending($sock);
print "1ret = ".read($sock, $tmp, 1)."\n"; print "tmp $tmp\n"; stillpending($sock);
print "8192ret = ".read($sock, $tmp, 8192)."\n"; print "tmp $tmp\n"; stillpending($sock);
send($sock, 'blah', 0);

close($sock);

服务器输出:
accepted 127.0.0.1:39944

带有binmode注释的客户端输出(正在使用Perlio层):
layers before = unix, perlio
layers after = unix, perlio
1ret = 1
tmp 1
no more
1ret = 1
tmp 2
no more
1ret = 1
tmp 3
no more
1ret = 1
tmp 4
no more

永远以上的块。

客户端输出的binmode取消注释(未使用perlio层):
layers before = unix, perlio
layers after = unix
1ret = 1
tmp 1
still more
1ret = 1
tmp 2
still more
1ret = 1
tmp 3
still more
1ret = 1
tmp 4
still more
8192ret = 6
tmp 567890
no more

我的问题是,当显然(通过strace)第一次read()调用消耗了服务器发送的全部输出(进入我想象的某个内部缓冲区)时, select()停止返回该数据处于挂起状态。如果没有perlio层,则最后一个 read(..., 8192)也将在其上阻塞,也不会阻塞。

我想我已经解决了我的问题(弹出perlio层),但是我很好奇其他人的想法是什么?即使第一个perl读取(带有perlio层)已将所有内容都读入内存, select()仍会报告挂起的 no more数据,这是一个错误吗?

还有其他人遇到类似的问题吗?

最佳答案

这是预料之中的:如果使用的是select(),则由于存在缓冲,因此需要使用sysread()而不是read()(正如您发现的那样:)。

perldoc -f select:

WARNING: One should not attempt to mix buffered I/O (like "read" or ) with "select", except as permitted by POSIX, and even then only on POSIX systems. You have to use "sysread" instead.

关于perl - Perl中的套接字编程,Perlio层有问题吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3006381/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com