2010-06-09 25 views
1

我注意到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層)已將所有內容讀入內存?

是否有其他人遇到過類似的問題?

回答

8

這是預期的:如果您使用的是select(),則需要使用sysread()而不是read(),因爲緩衝(因爲您已經發現:)。

perldoc -f select

警告:一個不應該試圖用「選擇」,混合緩衝I/O(如 「讀取」或),除了由POSIX, 所允許的,甚至然後僅在POSIX系統。您必須改用「sysread」 。

+1

啊,yikes ...我可能已經讀了一百遍,但忘記了這一點: - /謝謝指出。 – dlamotte 2010-06-09 13:59:24