Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl';s AnyEvent::IRC::客户端库在发送消息后未关闭_Perl_Irc_Anyevent - Fatal编程技术网

Perl';s AnyEvent::IRC::客户端库在发送消息后未关闭

Perl';s AnyEvent::IRC::客户端库在发送消息后未关闭,perl,irc,anyevent,Perl,Irc,Anyevent,我正在探索AnyEvent::IRC::Client库,以便将消息列表发送到IRC通道。我遵循Metapan站点(ref:)中的示例代码,只是我需要发送一个消息列表,而不是一条消息。因此,我能够成功地将阵列中的所有消息发送到IRC通道。问题是事件循环在结束时没有关闭(即,我必须按Ctrl+C来终止程序)。因此,任何关于如何关闭事件循环的见解都将不胜感激。谢谢 # Send some messages to IRC channel use strict ; use warnings 'all' ;

我正在探索AnyEvent::IRC::Client库,以便将消息列表发送到IRC通道。我遵循Metapan站点(ref:)中的示例代码,只是我需要发送一个消息列表,而不是一条消息。因此,我能够成功地将阵列中的所有消息发送到IRC通道。问题是事件循环在结束时没有关闭(即,我必须按Ctrl+C来终止程序)。因此,任何关于如何关闭事件循环的见解都将不胜感激。谢谢

# Send some messages to IRC channel
use strict ;
use warnings 'all' ;
no warnings 'uninitialized' ;
use AnyEvent ;
use AnyEvent::IRC::Client ;
use Data::Dumper ;
sub say { print @_, "\n" }

my @messages = ( 'msg1','msg2','msg3','msg4','msg5','msg6','msg7','msg8','msg9','msg10' ) ;

sendIrc( 'ircServer', 6667, '#ircChannel1', 'user123', 'psswd', \@messages ) ;

sub sendIrc {#Params: ircServer(Str), port(Int), channel(Str), nick(Str), psswd(Str), messages(ArrRef<Str>) ; #Return: void ;
  my ( $server, $port, $chan, $nick, $psswd, $messages ) = @_ ;
  my $timer ;
  my $condVar = AnyEvent->condvar ;
  my $con = AnyEvent::IRC::Client->new ;
  
  $con->reg_cb( connect => sub {
    my ( $cond, $err ) = @_ ;
    if ( defined $err ) {
      warn "connect error: $err\n" ;
      return ;
    }#end if
  }) ;

  $con->reg_cb( registered => sub {
    say "User is in!" ;
  }) ;

  $con->reg_cb( disconnect => sub {
    say "User is out!" ;
  }) ;

  $con->reg_cb( sent => sub {
    my ( $con ) = @_ ;
    if ( $_[2] eq 'PRIVMSG' ) {
      say "Msg sent!" ;
      $timer = AnyEvent->timer (
        after => 1 ,
        cb    => sub {
          undef $timer ;
          $condVar->end ;
        }#end callback
      );#end timer
    }#end if
  }) ;

  $con->connect( $server, $port, { nick => $nick, password => $psswd } ) ;
  for my $msg ( @$messages ) {
    $condVar->begin ;
    $con->send_srv( PRIVMSG => ( $chan, $msg ) ) ;
  }#end for
  $condVar->wait ;
  $con->disconnect ;
  return ;
}#end sub
#向IRC频道发送一些消息
严格使用;
使用“全部”警告;
没有“未初始化”的警告;
使用任何事件;
使用AnyEvent::IRC::Client;
使用数据::转储程序;
子语句{print@,“\n”}
my@messages=('msg1'、'msg2'、'msg3'、'msg4'、'msg5'、'msg6'、'msg7'、'msg8'、'msg9'、'msg10');
sendIrc('ircServer',6667',#ircChannel1','user123','psswd',\@messages);
子发送irc{#参数:ircServer(Str)、port(Int)、channel(Str)、nick(Str)、psswd(Str)、messages(ArrRef);#返回:void;
我的($server、$port、$chan、$nick、$psswd、$messages)=@;
我的$timer;
my$condVar=AnyEvent->condVar;
my$con=AnyEvent::IRC::Client->new;
$con->reg_cb(连接=>sub{
我的($cond,$err)=@;
如果(定义为$err){
警告“连接错误:$err\n”;
返回;
}#如果结束
}) ;
$con->reg_cb(已注册=>sub{
说“用户在!”;
}) ;
$con->reg_cb(断开连接=>sub{
说“用户出去了!”;
}) ;
$con->reg_cb(已发送=>sub{
我的($con)=@;
如果($u[2]等式'PRIVMSG'){
说“发送消息!”;
$timer=AnyEvent->timer(
在=>1之后,
cb=>sub{
未定义$计时器;
$condVar->end;
}#结束回调
)##结束计时器
}#如果结束
}) ;
$con->connect($server,$port,{nick=>$nick,password=>$psswd});
对于我的$msg(@$messages){
$condVar->begin;
$con->send_srv(PRIVMSG=>($chan,$msg));
}#结束
$condVar->等待;
$con->disconnect;
返回;
}#端接头

问题是,
AnyEvent::IRC::Client
将消息排队,并立即发出
sent
事件。当消息实际发送到服务器时,似乎没有触发事件。此外,处理每条消息需要一定的时间。我修改了您的代码以跟踪活动作业的数量并相应地重置计时器。这不是一个稳健的解决方案。如果每个作业的估计时间发生变化,则此操作将失败

use strict ;
use warnings 'all' ;
no warnings 'uninitialized' ;
use AnyEvent ;
use AnyEvent::IRC::Client ;
use Data::Dumper ;
sub say { print @_, "\n" }
my @messages = map {"msg$_"} 0..10 ;

sendIrc( 'ircServer', 6667, '#ircChannel1', 'user123', 'psswd', \@messages ) ;

sub sendIrc {#Params: ircServer(Str), port(Int), channel(Str), nick(Str), psswd(Str), messages(ArrRef<Str>) ; #Return: void ;
  my ( $server, $port, $chan, $nick, $psswd, $messages ) = @_ ;
  my $timer;
  my $jobs = 0;# count of jobs
  my $time_per_job = 1;# seconds
  my $condVar = AnyEvent->condvar ;
  my $con = AnyEvent::IRC::Client->new ;
  my $cb = sub {shift->send("done\n")};
  $condVar->begin($cb); # one begin/end pair to wrap everything

  $con->reg_cb( connect => sub {
    my ( $cond, $err ) = @_ ;
    if ( defined $err ) {
      warn "connect error: $err\n" ;
      return ;
    }#end if
  }) ;

  $con->reg_cb( registered => sub {
                    say "User is in!" ;
  }) ;

  $con->reg_cb( disconnect => sub {
    say "User is out!" ;
  }) ;

  $con->reg_cb( sent => sub {
    if ( $_[2] eq 'PRIVMSG' ) {
        $jobs++;
        print "jobs waiting: $jobs\n";
        $timer = AnyEvent->timer (
            after => $jobs * $time_per_job ,
            cb    => sub{ while ($jobs){ $condVar->end;
                                         $jobs--;}
                      },#end callback
         );#end timer
    }#end if
  }) ;

  $con->connect( $server, $port, { nick => $nick, password => $psswd } ) ;

  for my $msg ( @$messages ) {
      $con->send_srv( PRIVMSG => ( $chan, $msg ) ) ;
      $condVar->begin;
  }#end for
  
  $condVar->end;
  my $isDone = $condVar->recv;
  print $isDone;
  $con->disconnect ;
  return ;
}#end sub
使用严格;
使用“全部”警告;
没有“未初始化”的警告;
使用任何事件;
使用AnyEvent::IRC::Client;
使用数据::转储程序;
子语句{print@,“\n”}
我的@messages=map{“msg$\}0..10;
sendIrc('ircServer',6667',#ircChannel1','user123','psswd',\@messages);
子发送irc{#参数:ircServer(Str)、port(Int)、channel(Str)、nick(Str)、psswd(Str)、messages(ArrRef);#返回:void;
我的($server、$port、$chan、$nick、$psswd、$messages)=@;
我的$timer;
我的$jobs=0;#工作计数
我的$time_每个作业=1;#秒
my$condVar=AnyEvent->condVar;
my$con=AnyEvent::IRC::Client->new;
my$cb=sub{shift->send(“done\n”)};
$condVar->begin($cb)#一对begin/end可以包装所有内容
$con->reg_cb(连接=>sub{
我的($cond,$err)=@;
如果(定义为$err){
警告“连接错误:$err\n”;
返回;
}#如果结束
}) ;
$con->reg_cb(已注册=>sub{
说“用户在!”;
}) ;
$con->reg_cb(断开连接=>sub{
说“用户出去了!”;
}) ;
$con->reg_cb(已发送=>sub{
如果($u[2]等式'PRIVMSG'){
$jobs++;
打印“正在等待的作业:$jobs\n”;
$timer=AnyEvent->timer(
after=>$jobs*$time\u per\u job,
cb=>sub{while($jobs){$condVar->end;
$jobs--;}
},#结束回调
)##结束计时器
}#如果结束
}) ;
$con->connect($server,$port,{nick=>$nick,password=>$psswd});
对于我的$msg(@$messages){
$con->send_srv(PRIVMSG=>($chan,$msg));
$condVar->begin;
}#结束
$condVar->end;
我的$isDone=$condVar->recv;
打印$isDone;
$con->disconnect;
返回;
}#端接头

您重用了
$timer
,因此它只会被调用一次,并且您会得到不平衡的begin/end调用。您可以在回调中重置计时器,并确保立即调用
->end
。或者更容易从回调中删除计时器,并在断开连接之前使用计时器。Hi@clamp,所以为了澄清,我只需删除“my$timer;”主声明行并使用单独的计时器实例,即“$con->reg_cb(sent=>sub{…”中的“my$timer=AnyEvent->timer(…)”块,这应该是正确的吗?不,这将导致所有计时器同时运行。不幸的是,
sent
触发太早,您必须给它一秒钟的时间才能真正完成。您需要检查计时器是否仍在运行(已定义)如果是这样的话,用累积的时间重新设定。这就是为什么我认为在断开连接之前设置一个时间更长的计时器会更容易。因此,如果采用单计时器方法,则为“之后”提供的秒数属性必须与数组中的消息数成比例,即,如果有10条消息,那么它将是:“after=>10;如果有20条消息,那么它将是“after=>20”,对吗?在我的环境中,似乎就是这样。消息排队,每一条都需要大约1秒。感谢@clamp的帮助!