我注意到perl中perlio層的一些問題。帶我一個好日子來追蹤它,並希望其他人知道這件事?關於這一點最可怕的是,由於它太低級,我擔心它會降低代碼的可移植性。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);
服務器輸出:與binmode
accepted 127.0.0.1:39944
客戶端輸出評論(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)()調用消耗了整個輸出由服務器發送(進入一些內部緩衝區我想象)。當沒有perlio層時,最後的read(..., 8192)
也會被阻塞,它不會阻塞。
我想我有解決我的問題(彈出perlio層),但我很好奇別人的想法是什麼?是否select()
報告no more
數據掛起,即使第一次perl讀(使用perlio層)已將所有內容讀入內存?
是否有其他人遇到過類似的問題?
啊,yikes ...我可能已經讀了一百遍,但忘記了這一點: - /謝謝指出。 – dlamotte 2010-06-09 13:59:24