1

我正在尝试使用 Lincoln Stein 的Network Programming With Perl中的一组 IO 模块,并遇到以下错误:

Can't locate object method "blocking" via package "IO::LineBufferedSessionData" 
at /mxhome/charrison/private/perl/IO/SessionData.pm line 22.

我从 Addison/Wesley 站点为本书下载的模块集合不包含 blocking() 子例程,经过一番挖掘后,我发现它希望调用 IO::Socket 中的 blocking() 子例程的证据或者 IO::File,或者 IO::Handle.... 实际上在 IO::Handle 中有一个 blocking() 方法。

这是 IO::SessionData 模块的顶部部分,包括它正在吐槽的那一行:

package IO::SessionData;
# file: IO/SessionData.pm                                                                                                   
# Figure 13.5: The IO::SessionData Module Code                                                                              

use strict;
use Carp;
use IO::SessionSet;
use Errno 'EWOULDBLOCK';
use vars '$VERSION';
$VERSION = 1.00;

use constant BUFSIZE => 3000;

# Class method: new()                                                                                                       
# Create a new IO::SessionData object.  Intended to be called from within                                                   
# IO::SessionSet, not directly.                                                                                             
sub new {
  my $pack = shift;
  my ($sset,$handle,$writeonly) = @_;
  # make the handle nonblocking        
  #######################################################################                                                                                     
  $handle->blocking(0);       # <=== THIS IS THE CALL IT FAILS ON
  #######################################################################
  my $self = bless {
                outbuffer   => '',
                sset        => $sset,
                handle      => $handle,
                write_limit => BUFSIZE,
                writeonly   => $writeonly,
                choker      => undef,
                choked      => undef,
               },$pack;
  $self->readable(1) unless $writeonly;
  return $self;
}

我不知道这是否足以解决问题。我对模块或面向对象的 Perl 了解甚少。我猜作者打算blocking在某个超类中调用一个方法(例如 IO::Handle?)。这本书写于 2001 年,也许有些规则已经改变。或者文本可能有错误。任何人都可以提出解决方案,或要求提供更多信息吗?

更新 1:confess这是在有问题的阻塞()调用之前 生成的堆栈跟踪:

/Users/chap/private/wdi/server$ ./server_template -v
 at /Users/chap/private/wdi/lib/IO/SessionData.pm line 21.
    IO::SessionData::new('IO::LineBufferedSessionData', 'IO::LineBufferedSet=HASH(0x7fcbe19bd450)', 'IO::Socket::INET=GLOB(0x7fcbe18a8070)', undef) called at /Users/chap/private/wdi/lib/IO/LineBufferedSessionData.pm line 21
    IO::LineBufferedSessionData::new('IO::LineBufferedSessionData', 'IO::LineBufferedSet=HASH(0x7fcbe19bd450)', 'IO::Socket::INET=GLOB(0x7fcbe18a8070)', undef) called at /Users/chap/private/wdi/lib/IO/SessionSet.pm line 46
    IO::SessionSet::add('IO::LineBufferedSet=HASH(0x7fcbe19bd450)', 'IO::Socket::INET=GLOB(0x7fcbe18a8070)') called at /Users/chap/private/wdi/lib/IO/SessionSet.pm line 136
    IO::SessionSet::wait('IO::LineBufferedSet=HASH(0x7fcbe19bd450)') called at /Users/chap/private/wdi/lib/IO/LineBufferedSet.pm line 24
    IO::LineBufferedSet::wait('IO::LineBufferedSet=HASH(0x7fcbe19bd450)') called at ./server_template line 221

如您所见,new() 正在内部被调用。(我的应用程序在堆栈的底部;其他所有内容都来自本书。)

4

1 回答 1

1

发生的事情是该类需要一个传递给它的具有该->blocking()方法的参数(第二个参数)。应该像这样调用它:

my $sset = ...;
my $handle = IO::Handle->new( ... ); #  build your IO handle
my $writeonly = ... ; 

my $session_data = IO::SessionData->new($sset, $handle, $writeonly);

第一行,

my $pack = shift;

是类名。这应该是惯用的名称:

my $class = shift;

new当通过对象调用语法(语法)调用时,会自动添加这个额外的变量。通过移位,它会从参数列表Object::Name->method中删除该类名。@_其余的值是构造函数的参数。由于调用了第二个参数$handle并调用了该方法,因此您需要向它传递一个具有该方法的变量。处理该方法的任何东西都可以,但您可能需要某种 IO::Handle。:)

对更新 1 的回应:

如果您查看跟踪,您将看到:

IO::SessionData::new('IO::LineBufferedSessionData', 'IO::LineBufferedSet=HASH(0x7fcbe19bd450)', 'IO::Socket::INET=GLOB(0x7fcbe18a8070)', undef) 

作为调用该方法的事物。The IO::Socket::INETis an IO::Socketwhich is an IO::Handle,所以它应该能够有->blocking()可用的方法。21号线是什么?

于 2013-01-15T01:25:11.137 回答