2011-04-08 68 views
5

我正試圖通過一個小的Perl學習項目,需要從套接字讀取4個無符號整數。我無法獲得超過1整數讀取,並且在挖掘後我找到了一個解決方案。但是,我需要了解什麼,我沒有做正確的socket-> recv()與<>?

例1(通過一對夫婦的Perl書籍,perldocs文檔,等去了也沒有用。): 下面是成功的解決方案代碼(original),假設套接字連接成功,如下所示:

{ 
    local $/ = \16; # make <> read in 16 bytes with one swoop. 
    my @integers = unpack "IIII", <$sock>; 
    print "numbers: @val\n"; 
} 

示例2:我在下面嘗試了這一點。如果我打印輸入拆包之前,我只得到一個整數:

my $input; 
$sock->recv($input,16,0); 
my @integers = unpack("IIII", $input); 

具體的問題:

  1. 在例1中,到底是什麼「$ /」?它是如何「改變」<>,我認爲讀了STDIN?
  2. 在示例2中,有什麼理由說明爲什麼我的recv()不能使用超過一個整數的套接字?我的理解(每perldoc)是「SIZE」參數默認爲「字節」,整數是4個字節?

任何幫助,指針等讚賞。順便說一句,「學習項目」是overthewire.org - 非常酷的東西。

+1

爲了獲得簡單的文檔資料:[perlvar $ /](http://p3rl.org/var#%24INPUT_RECORD_SEPARATOR); '''''對於[readline](http://p3rl.org/readline) – daxim 2011-04-08 19:20:20

回答

1

至於1)

那麼,<>採取任何文件句柄,包括插座。這是一個約定,你可以將它留空,在這種情況下,假設某種理智的默認行爲。見perldoc perlop(在裏面搜索<>)。

而特殊變量$/是記錄分隔符,它默認爲「\ n」。你可以解開它,並立即讀取整個文件(這就是所謂的sl))。詳情請參見perldoc perlvar\number的情況也存在)。

+0

只是一個不同的名稱。雖然我確實使用了所有的註釋,但這對我很有用。我永遠不會讀/ readline/recv工作。但現在我明白瞭如何使用<>和$ /,我很樂意繼續前進。謝謝您的幫助。 – 1111000110 2011-04-09 22:24:39

4

是你的套接字TCP或UDP?

recv是比<>/readline更低級別的例程。它或多或少直接映射到recv(2)系統調用。如果套接字數據以4個4字節數據包到達,則即使提供了更大的緩衝區,recv也會立即返回。如果在首次調用recv()之前全部4個數據包到達,那麼無論是獲取所有數據還是僅獲取一個數據包取決於它是TCP還是UDP。

如果您使用的是TCP,那麼數據包在飛行中可能會被分段。 16字節的有效負載不太可能發生,但最好的做法是不要假設即使您知道服務器一次發送全部數據,也會一次顯示16個字節的數據。網絡應用程序通常需要緩衝傳入的數據,或者,您可以通過使用$/ = \16指定16字節的記錄來讓Perl爲您執行此操作。

另一種可能性,這是我找到比<>對這種I/O使用的更自然的,是使用readsysread函數(或OO當量,這是在超類IO::SocketIO::Handle定義)。那些需要長度的參數,但是和以前一樣,你不應該假設整個緩衝區會一次被填滿。

1

readreadline(又名<>)在返回之前等待所請求的字符數量可用。如果發生錯誤或EOF,它只會返回更少的字符,在這種情況下,下一次讀取將返回錯誤或EOF。

sysread只要某些字符可用,即使少於請求數量,也會返回。

根據你在說什麼,recv就像sysread。如果你想要16個字符,你必須循環,直到你有16個字符或使用readreadline