【问题标题】:Socket programming in perl, problem with perlio layer?perl 中的套接字编程,perlio 层的问题?
【发布时间】:2011-03-01 16:29:11
【问题描述】:

我注意到 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

我的问题是 select() 当显然(通过 strace)第一个 read() 调用已经消耗了服务器发送的整个输出(我想象的某个内部缓冲区)时,select() 停止返回该数据未决。最后一个read(..., 8192)在没有perlio层的情况下也会阻塞,它不会阻塞。

我想我有解决问题的方法(弹出 perlio 层),但我很好奇其他人的想法是什么?即使第一次 perl 读取(使用 perlio 层)已将所有内容读入内存,select() 报告 no more 数据待处理是否是一个错误?

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

【问题讨论】:

    标签: perl sockets select


    【解决方案1】:

    这是意料之中的:如果您使用的是select(),则需要使用sysread() 而不是read(),因为缓冲(正如您所发现的:)。

    来自perldoc -f select

    警告:不应尝试混合缓冲 I/O(如 "read" 或 ) 与 "select",除非 POSIX 允许, 甚至只有在 POSIX 系统上。你必须使用“sysread” 而是。

    【讨论】:

    • 啊,哎呀...我可能已经读了一百遍了,但是忘记了:-/感谢您指出这一点。
    猜你喜欢
    • 2011-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多