[英]How can I deteremine if I'd read something from a socket?
以下代碼應該從套接字讀取幾行,但行數不確定。
use warnings;
use strict;
use IO::Socket::INET;
my $server = shift;
my $port = shift;
my $sock = new IO::Socket::INET (
PeerAddr => $server,
PeerPort => $port,
Proto => 'tcp',
Timeout => 1,
Blocking => 0
)
or die "Could not connect";
while (my $in = <$sock>) {
print "$in";
}
print "Received last line\n";
不幸的是,盡管我已將Blocking => 0
設置為$in = <$sock>
部分正在阻塞,但服務器不再發送任何文本。 因此,將不會打印Received last line
。
因此,我嘗試use IO::Select
改善行為:
use warnings;
use strict;
use IO::Socket::INET;
use IO::Select;
my $server = shift;
my $port = shift;
my $sock = new IO::Socket::INET (
PeerAddr => $server,
PeerPort => $port,
Proto => 'tcp',
Timeout => 1,
Blocking => 1
)
or die "Could not connect";
my $select = new IO::Select;
$select -> add($sock);
sleep 1;
while ($select -> can_read) {
my $in = <$sock>;
print $in;
}
第二種方法僅打印第一個發送的行,然后似乎永遠阻塞。
既然看到了這樣的示例,我相信問題是Windows,我正在其上嘗試運行這些腳本。
有沒有一種方法可以實現非阻塞讀取?
當使用select
(由can_read
)時,它違反了阻止IO的目的。 您還必須避免緩沖IO,因為系統(即select
)不知道庫緩沖區中的任何數據。 這意味着您不能將select
與read
, readline
(又名<>
和<$fh>
)和eof
。 您必須使用sysread
。
my %clients;
for my $fh ($select->can_read()) {
my $client = $clients{$fh} //= {};
our $buf; local *buf = $client->{buf} //= ''; # alias my $buf = $client->{buf};
my $rv = sysread($sock, $buf, 64*1024, length($buf));
if (!defined($rv)) {
my $error = $!;
$select->remove($fh);
delete($clients{$fh});
# ... Handle error ...
next;
}
if (!$rv) {
$select->remove($fh);
delete($clients{$fh});
# ... Handle EOF ... # Don't forget to check if there's anything in $buf.
next;
}
... remove any complete messages from $buf and handle them ...
}
如果您想一次閱讀一行,可以使用
while ($buf =~ s/^([^\n]*)\n//) {
process_msg($client, $1);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.