簡體   English   中英

Perl中的套接字編程,Perlio層有問題嗎?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM