簡體   English   中英

如果我要從套接字讀取內容,該如何確定?

[英]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 )不知道庫緩沖區中的任何數據。 這意味着您不能將selectreadreadline (又名<><$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.

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