我正在尝试使用Lincoln Stein的使用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中的blocking()子程序的证据。 :: Socket或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年,也许一些规则已经改变。或许文本有bug。有人可以建议解决方案,或要求进一步的信息吗?
UPDATE 1:这是在违规的blocking()调用之前由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()正在内部调用。 (我的应用程序位于堆栈的底部;其他所有内容都来自本书。)
答案 0 :(得分: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。 :)
对UPDATE 1的回复:
如果您查看跟踪,您会看到:
IO::SessionData::new('IO::LineBufferedSessionData', 'IO::LineBufferedSet=HASH(0x7fcbe19bd450)', 'IO::Socket::INET=GLOB(0x7fcbe18a8070)', undef)
作为调用方法的东西。 IO::Socket::INET
是IO::Socket
,IO::Handle
,因此应该可以使用->blocking()
方法。什么是第21行?