2012-02-10 87 views
4

這是我當前的代碼:標值誤差(與IO ::插座)

#!/usr/bin/perl -w 

use strict; 
require IO::Socket; 

while (<>) { 
     chomp(my $host = $_); 
     my @header; 

     print "Connecting to: $host\n"; 
     my $socket = new IO::Socket::INET(
       PeerAddr => $host, 
       PeerPort => 80, 
       Proto => 'tcp') || print "Could not connect: $!\n"; 

     print "Connected.\n"; 

     print $socket "GET/HTTP/1.0\n\n"; 
     my $i = 0; 
     while (<$socket>) { 
       @header[$i] = $_; 
       $i++; 
     } 

     $i = 0; 
     print "--------------------------------------\n"; 
     while ($i <= 8) { 
       print "@header[$i++]"; 
     } 

     print "-------------------------------------\n"; 
     print "Finished $host\n\n"; 
} 

如果要同時通過IP的列表,以及主機關閉,而不是繼續到下一個IP,它會給我一個錯誤「在使用」strict refs「時,不能使用字符串(」1「)作爲符號ref。

如果我再改變@header [$ i] = $ ;到$ he​​ader [$ i] = $;我也得到同樣的錯誤。我怎樣才能使這個腳本更好。

+1

什麼行導致錯誤?另外,如果將'$ socket'作爲新的'IO :: Socket :: INET'對象的創建不成功,你應該或者'死掉'或者移動到下一個參數。 – 2012-02-10 00:33:47

+2

@header [$ i]'不正確,即使將它改爲正確的東西也不能解決錯誤。 – geoffspear 2012-02-10 00:35:22

+1

@Wooble - 很好。爲什麼總是應該啓用'warnings'編譯指示的另一個原因。 – 2012-02-10 00:38:08

回答

10

的問題是在你設置$socket方式:由於您使用的||運營商,其中有precedence高於=

my $socket = new IO::Socket::INET(
     PeerAddr => $host, 
     PeerPort => 80, 
     Proto => 'tcp') || print "Could not connect: $!\n"; 

,這種說法被解析爲

my $socket = (new IO::Socket::INET(...) || print ...); 

如果new IO::Socket::INET返回一個錯誤值(如果連接失敗),print將執行其retu價值(通常是1)將被分配到$socket。 當你再嘗試使用$socket在聲明的indirect object

print $socket "GET/HTTP/1.0\n\n"; 

的Perl注意到的價值1並不是真正的對象引用,並拋出你報告的錯誤。

如果你使用的||低優先級運營商,而不是or$socket值會一直undef,而不是1,並且你會收到錯誤信息會一直像Can't use an undefined value as a symbol reference ...。當然,這不會真的解決你的問題,但至少可以讓它更容易診斷。

要真正解決問題,您需要修復代碼,以便在連接失敗時不會繼續執行循環體的其餘部分。要做到這一點的一種方法是這樣的:

my $socket = new IO::Socket::INET(
     PeerAddr => $host, 
     PeerPort => 80, 
     Proto => 'tcp'); 

unless ($socket) { 
     print "Could not connect: $!\n"; 
     next; # skip the rest of the loop 
} 
+0

+1好收穫。 '' – TLP 2012-02-10 02:53:15

0

那不是簡單的解決方案是使用低優先級的版本「或」具有比「=」低優先級?

my $socket = new IO::Socket::INET(
    PeerAddr => $host, 
    PeerPort => 80, 
    Proto => 'tcp') 
     or print "Could not connect: $!\n"; 

事實上,運算符'或'和'xor'具有最低的運算符優先級(請參閱perlop)。