2009-10-02 87 views
1

我試圖使用IO :: Socket :: INET連接到Web服務(是的,我知道有很多更好的模塊可以做到這一點,沒有它們,不能添加它們,所以請不要提示它),但是我正在等待(等待響應)。IO :: Socket獲取響應時超時

這裏是我的代碼的基本癥結(我以前填充所有適當的標題的內容,並對其進行設置等):

$httpSock->print($content); 

my @lines = $httpSock->getlines(); 
foreach my $line (@lines) { 
    print $line; 
} 

看來,我的要求是立即進行,然後等待大約2分鐘後再吐出迴應。如果我改變代碼使用原始套接字recv代替getlines(),鼻翼:

$httpSock->recv($data, 1024); 

我得到的立即響應(雖然只有前1024個字符)。我在這裏做錯了什麼?我使用的IO :: Socket版本足夠晚,autoflush應該默認啓用,但明確地打開它似乎沒有任何區別。我可能也只是繼續讀取套接字,直到我得到整個響應,但這絕對比使用getlines()<$httpSock>更混亂。

在此先感謝。

回答

3

我遇到了一個問題,使用您發佈的代碼段重新創建問題。下面是我測試的代碼:

use strict; 
use warnings; 
use IO::Socket; 

my $httpSock = new IO::Socket::INET(
    PeerAddr => 'www.google.com', 
    PeerPort => '80', 
    Proto => 'tcp', 
); 

my $content = "HEAD/HTTP/1.0\r\nHost: www.google.com\r\n\r\n"; 

$httpSock->print($content); 
my @lines = $httpSock->getlines(); 
foreach my $line (@lines) { 
    print $line; 
} 

這裏的結果:

$ time ./1.pl 
HTTP/1.0 200 OK 
-snip- 

real 0m0.084s 
user 0m0.025s 
sys 0m0.007s 
+1

是的,這與我所擁有的非常接近。進一步的調查讓我相信這是一種EOF問題。如果我使用'getline()'(在一個循環中),它會抓取最後一行。如果我使用'recv()',它將獲得除最後一位以外的所有數據。這些幫助有用? – Morinar 2009-10-02 18:22:09

+0

我也在執行POST而不是HEAD或GET。不知道這是否有什麼區別... – Morinar 2009-10-02 18:26:32

+0

您的示例也適用於我,但是如果您將HTTP/1.0更改爲HTTP/1.1(這是我使用的),您的示例與我的一樣掛起。 HTML/1.0和HTML/1.1有什麼區別? – Morinar 2009-10-02 18:43:24

3

的問題是,getlines()等待,直到連接被關閉。如果您連接的Web服務沒有關閉連接,getlines函數將會等待,並考慮更多數據。如果在2分鐘左右之後連接超時,getlines將看到連接關閉,並將收到的線路返回給您。另一方面,Recv將抓取所有連接上的預定限制,並將其返回到您立即傳送的緩衝區,但是如果當前沒有數據,它將等待直到它獲得一些數據。我知道你認爲它的凌亂,但是這可能會制定出適合你:

$httpSock->recv($buf, 1024); 
$message = ""; 
while (length($buf) > 0) { 
    $message .= $buf; 
    $httpSock->recv($buf, 1024, MSG_DONTWAIT); 
} 
print $message; 

的MSG_DONTWAIT會導致recv的不等待消息,如果連接是空的。您還可以將1024增加到某個大數字以減少循環數,甚至可能一次獲得整個消息。

這也應該讓你保持開放的插座進一步使用,直到你自己關閉它。

我想知道是否谷歌示例工作,因爲google.com是響應後關閉連接。

+0

那裏有一些很好的想法,但請參閱我對「真正」問題/解決方案的其他答案的評論。 – Morinar 2009-10-02 21:06:08