Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.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中正确使用TCP客户端的IO::Socket::INET_Perl_Sockets_Tcp - Fatal编程技术网

在perl中正确使用TCP客户端的IO::Socket::INET

在perl中正确使用TCP客户端的IO::Socket::INET,perl,sockets,tcp,Perl,Sockets,Tcp,我有一个关于如何使用IO::Socket的问题;我有一个脚本,应该经常运行,监视星号服务器的某些事件。当这些事件发生时,脚本通过TCP套接字将数据从事件发送到另一台服务器。我发现插座偶尔会关闭。我的问题是,我是应该使用一个套接字,并让它永远打开(并找出+为什么阻止它关闭),还是应该为发送的每一位数据打开并关闭一个新的套接字? 我在这方面的经验非常少,我已经阅读了所有文档,但没有找到我想要的答案。以下是我迄今为止得到的一个样本: #!/usr/bin/perl use Asterisk::AMI;

我有一个关于如何使用IO::Socket的问题;我有一个脚本,应该经常运行,监视星号服务器的某些事件。当这些事件发生时,脚本通过TCP套接字将数据从事件发送到另一台服务器。我发现插座偶尔会关闭。我的问题是,我是应该使用一个套接字,并让它永远打开(并找出+为什么阻止它关闭),还是应该为发送的每一位数据打开并关闭一个新的套接字?
我在这方面的经验非常少,我已经阅读了所有文档,但没有找到我想要的答案。以下是我迄今为止得到的一个样本:

#!/usr/bin/perl
use Asterisk::AMI;
use IO::Socket;
use strict;
use warnings;

my $sock = new IO::Socket::INET (
  PeerAddr => '127.0.0.1',
  PeerPort => '1234',
  Proto => 'tcp',
);

sub newchannel {
  my ($ami, $event) = @_;

  if ($event->{'Context'} eq "from-trunk") {

    my $unique_id = $event->{'Uniqueid'};
    my $this_call = $call{$unique_id};

    $this_call->{caller_name} = $event->{'CallerIDName'};
    $this_call->{caller_number} = $event->{'CallerIDNum'};
    $this_call->{dnis} = $event->{'Exten'};

    $call{$unique_id} = $this_call;
  };

}

sub ringcheck {
  my ($ami, $event) = @_;

  if ($event->{SubEvent} eq 'Begin') {
    my $unique_id = $event->{UniqueID};
    if (exists $call{$unique_id}) {

      my $this_call = $call{$unique_id};

      $this_call->{system_extension} = $event->{Dialstring};
      $this_call->{dest_uniqueid}  = $event->{DestUniqueID};


      printf $sock "R|%s|%s|%s||%s\n",
        $this_call->{caller_name},
        $this_call->{caller_number},
        $this_call->{system_extension},
        $this_call->{dnis};

      $this_call->{status}  = "ringing";
  }
}
还有更多,但这显示了我觉得应该在哪里启动/停止一个新的套接字(在ringcheck子中)

如果你需要我澄清或补充什么,请告诉我


谢谢

是否最好为每条消息建立新连接或保持连接打开取决于以下几个因素:

  • 与建立连接相关的开销是否很大?这取决于诸如需要发送消息的频率和网络连接的质量等因素

    如果远程端是“localhost”,如上面的示例脚本所示,那么这不太可能是一个问题,事实上,在这种情况下,我建议使用Unix域套接字

  • 远端是否正在发送任何信息?如果任何一方都有异步消息要发送,那么管理零星连接就更难了。但听起来你的情况并非如此

  • 通过保持连接打开,您是否有任何重要的资源被占用

请注意,我不认为随机连接辍学是一个很好的理由争辩每次建立一个新的连接。如果可能,最好在任何情况下诊断该问题。否则,无论采用何种方法,您都可能获得不可靠的性能

根据我的经验,在长时间保持的TCP连接中,出现看似随机的退出的一个非常常见的原因是中间跟踪防火墙。如果这些防火墙在一段时间内看不到任何活动,它们将断开连接,以节省自己的资源。我在一些工具中使用的一种方法是设置套接字选项,以便在套接字上保持激活状态,如下所示:

use Socket;
...
setsockopt($sock, SOL_SOCKET, SO_KEEPALIVE, 1);
这有两个好处——它会导致内核定期在您的连接上发送keepalive消息,即使一切都很安静,这本身就足以让一些防火墙感到高兴。此外,如果您的连接确实断开,您的程序可以立即发现,而不是下次您想写入它时(尽管您可能不会注意到,除非您定期检查套接字上的错误)

也许您最好的方法是设置SO_KEEPALIVE并保持套接字打开,但也可以在尝试写入时检查错误,如果有错误,请关闭并重新打开连接


也可能对您有用。

开销不重要。都是局域网,大概每10分钟不到一条消息。远端没有发送任何内容。没有任何重要的东西被用来做这些;我看不出有什么理由不让连接保持打开状态。我的部分问题是,我无法访问此连接的另一端,因此必须使用我所拥有的进行故障排除。你的回答非常有用,我将尝试keepalive选项,今天晚些时候再查看。再次感谢。看起来很有效,从那以后就再也没有掉过。谢谢你的回答。