2010-02-22 27 views
4

我有這個小腳本,它工作得很好,但有時候會失敗。它失敗2例:如何在我的Perl TCP腳本中診斷「無法確定對等地址」?

  1. 錯誤發送:Cannot determine peer address at ./tcp-new.pl line 52

  2. 沒有輸出或任何東西,只不過沒有帶來它得到了連接TCP客戶端。通常發生在我從服務器斷開連接後,回家並重新連接。要解決此重新啓動是必需的,它開始工作。有時,這個問題後面是問題點提到的1

注:當我拔下這不是問題的時間(除非錯誤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); 
     } 
    } 
    } 
} 

回答

2

Cannot determine peer address錯誤意味着getpeername()返回false。這可能意味着套接字已從另一端關閉,可能在can_write()呼叫和send呼叫之間關閉。您應該從選擇集中移除它並繼續前進。

+0

你可以更具體地說我怎麼能做到這一點。我沒有經驗與perl和tcp/udp選擇,所以我聽到你在說什麼,但不知道如何實現。 – MadBoy 2010-02-22 15:54:37

0

在腳本完全失敗而沒有任何錯誤消息的情況下,可能是由於未處理的信號,通常是SIGPIPE。如果套接字操作在發送操作期間收到信號,則可能發生這種情況我可以在我自己的系統中通過模擬許多高數據量併發連接到tcp服務器並同時終止這些客戶端連接,輕鬆地重現它。在你的腳本上運行strace,你可以清楚地看到信號。這就是說,我試圖找出如何重現「無法確定對方地址」的錯誤,但無濟於事......

+0

那你究竟在說什麼?你想和我有同樣的問題嗎? :) – MadBoy 2010-04-16 16:32:06

+0

我需要能夠重現錯誤的需求,所以我可以爲我的代碼實現健壯的自動化測試。 – 2010-04-17 19:17:57

1

發現同樣的問題,襪子沒有peeraddress。

展望IO ::插座在http://search.cpan.org/src/GBARR/IO-1.2301/IO/Socket.pm顯示:

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是在創建對象初始化,或者所提供的對端地址作爲第三個參數發送()。

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