2016-08-14 21 views
1

如何沖洗從開放獲得的管子手柄?

我試圖刷新一個管道句柄使用從IO::Handle模塊要麼autoflush()flush()方法從open獲得的,但我認爲這是行不通的。下面是一個例子:

host.pl

use feature qw(say); 
use strict; 
use warnings; 

my $client_pid = open (my $fh, '|-', 'client.pl') 
    or die "Could not open client: $!"; 
#$fh->autoflush(1); # adding this line does not help 
sleep 2; 
say "Host: sent message"; 
print $fh "Hello"; 
#print $fh "Hello\n"; # adding a newline works fine 
$fh->flush() or warn "$!"; # this does not work 
sleep 2; 
say "Host exits."; 
close $fh; 

client.pl

use feature qw(say); 
use strict; 
use warnings; 

say "Client running.."; 
chomp (my $line = <STDIN>); 
say "Client got line: '$line'"; 
sleep 1; 
say "Client exits.."; 

運行host.pl的輸出是:

Client running.. 
Host: sent message 
Host exits. 
Client got line: 'Hello' 
Client exits.. 

預期OUTP UT是:

Client running.. 
Host: sent message 
Client got line: 'Hello' 
Client exits.. 
Host exits. 

我知道我可以通過在字符串末尾添加一個新行解決這個問題要打印:

print $fh "Hello\n"; 

,但我很好奇,爲什麼$fh->flush()沒有在這裏工作?

+3

因爲客戶端正在使用'readline',所以它在''中循環直到'\ n'到達。 – melpomene

+0

@melpomene當然,我是盲目的!但問題是,如果有可能以其他方式閱讀郵件? –

+0

@Borodin我很好奇你爲什麼使用'language:lang-perl'編輯語法突出顯示?沒有添加標籤,語法突出顯示對我來說也很好。或者我錯過了什麼? –

回答

3

數據正在立即發送到客戶端,但客戶端等待換行符到達。


readline(針對<>是在你的程序的快捷方式)讀取,直到一個換行符將返回(雖然改變$/可以改變這種行爲遇到過的。如果你想要的數據是可用的,一旦返回一個電話,使用sysread

use BLOCK_SIZE => 64*1024; 

say "Client running.."; 
while (1) { 
    my $rv = sysread(\*STDIN, my $buf, BLOCK_SIZE); 
    die($!) if !defined($rv); 
    last if !$rv; 
    say "Got: $buf"; 
} 

注單打印可導致多塊接收數據。在實踐中,尤其是插座,而不是一個管道,你需要爲了取景郵件的一些方法來可靠地識別它們。例如,以下內容客戶希望定點封端的消息(前哨是一個新行):

use BLOCK_SIZE => 64*1024; 

say "Client running.."; 
my $buf = ''; 
while (1) { 
    my $rv = sysread(\*STDIN, $buf, BLOCK_SIZE, length($buf)); 
    die($!) if !defined($rv); 
    last if !$rv; 
    while ($buf =~ s/^([^\n]*)\n//) { 
     my $msg = $1; 
     say "Got: $msg"; 
    } 

    say "Got a partial message" if length($buf); 
} 

die("Premature EOF\n") if length($buf); 

嘗試發送:

$fh->autoflush(); 
print($fh "abc"); 
sleep(1); 
print($fh "def\n"); 
sleep(1); 
print($fh "ghi\njkl\nmno"); 
sleep(1); 
print($fh "pqr\n"); 

這可以適於處理長度前綴消息或任何其他消息格式。

+0

優秀的答案,這澄清了很多事情! –