如何在Perl TCP脚本中诊断“无法确定对等地址”?

时间:2010-02-22 14:19:18

标签: perl tcp udp

我有这个小脚本,它的工作做得很好,但有时它往往会失败。它在两种情况下失败:

  1. 发送错误:Cannot determine peer address at ./tcp-new.pl line 52

  2. 没有输出或任何东西,它只是无法提供连接到Tcp客户端的内容。通常它发生在我与服务器断开连接后,回家再次连接。要修复此重新启动是必需的,它开始工作。有时这个问题之后是第1点中提到的问题。

  3. 注意:当我在短时间内再次断开连接并重新连接时(除非发生错误nr 1),这不是问题。

    所以任何人都可以帮助我使这段代码更稳定,所以我不必每天都重启它吗?

    #!/usr/bin/perl
    use strict;
    use warnings;
    use IO::Socket;
    use IO::Select;
    
    my $tcp_port = "10008";
    my $udp_port = "2099";
    
    my $tcp_socket = IO::Socket::INET->new(
      Listen => SOMAXCONN,  LocalPort => $tcp_port,
      Proto  => 'tcp',      ReuseAddr => 1,
    );
    my $udp_socket = IO::Socket::INET->new(
      LocalPort => $udp_port, Proto => 'udp',
    );
    
    my $read_select  = IO::Select->new();
    my $write_select = IO::Select->new();
    
    $read_select->add($tcp_socket);
    $read_select->add($udp_socket);
    
    while (1) {
      my @read = $read_select->can_read();
    
      foreach my $read (@read) {
    
        if ($read == $tcp_socket) {
    
            my $new_tcp = $read->accept();
            $write_select->add($new_tcp);
    
        } elsif ($read == $udp_socket) {
    
            my $recv_buffer;
            $udp_socket->recv($recv_buffer, 1024, undef);
    
            my @write = $write_select->can_write();
            foreach my $write (@write) {
                $write->send($recv_buffer);
            }
        }
      }
    }
    

3 个答案:

答案 0 :(得分:2)

Cannot determine peer address错误表示getpeername()返回false。这可能意味着套接字已从另一侧关闭,可能在can_write()呼叫和send呼叫之间。你可能应该从选择集中删除它并继续前进。

答案 1 :(得分:1)

发现同样的问题,袜子没有穿着。

http://search.cpan.org/src/GBARR/IO-1.2301/IO/Socket.pm处查看IO :: Socket显示:

sub send { @_ >= 2 && @_ <= 4 or croak 'usage: $sock->send(BUF, [FLAGS, [TO]] +)'; 
my $sock = $_[0]; my $flags = $_[2] || 0; my $peer = $_[3] || $sock->peername; 
croak 'send: Cannot determine peer address' unless($peer);

因此,您必须注意在创建对象时初始化peername,或者将peer地址作为send()的第三个参数。

if (! $sock->peeraddr()) {
         $log->warn("No peer, will croak!");
}

答案 2 :(得分:0)

在脚本完全失败的情况下,没有任何错误消息,可能是由于未处理的信号,通常是SIGPIPE。如果套接字操作在发送操作期间获得信号,则会发生这种情况。通过模拟与tcp服务器的许多高数据量并发连接并同时终止这些客户端连接,我可以在我自己的系统中轻松地重现它。在脚本上运行strace,您可以清楚地看到信号。也就是说,我试图找出如何重现“无法确定对等地址”的错误,但无济于事....