[英]Socket programming in perl, problem with perlio layer?
我注意到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)
最后一個read(..., 8192)
也會在其上阻塞,也不會阻塞。
我想我有解決問題的方法(彈出perlio層),但我很好奇其他人的想法是什么? 即使第一個perl讀取(帶有perlio層)已將所有內容讀入內存, select()
no more
報告未決數據的錯誤?
還有其他人遇到類似的問題嗎?
這是預料之中的:如果您使用的是select()
read()
,則由於存在緩沖,因此您需要使用sysread()
而不是read()
(如您所知:)。
從perldoc -f select
:
警告:除非POSIX允許,否則不要嘗試將緩沖的I / O(如“ read”或)與“ select”混合使用,即使在POSIX系統上也是如此。 您必須使用“ sysread”代替。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.