簡體   English   中英

Java InputStream會自動拆分套接字消息

[英]Java InputStream automatically splits socket messages

我在Java中有一個非常奇怪的行為,我無法分辨這是出於故意還是偶然。

我有一個服務器的套接字連接,它向我發送一個請求的響應。 我正在使用以下循環從Socket讀取此響應,該循環封裝在try-with-resource中。

BufferedInputStream remoteInput = new BufferedInputStream(remoteSocket.getInputStream())
final byte[] response = new byte[512];
int bytes_read;
while ((bytes_read = remoteInput.read(response,0,response.length)) != -1) {
    // Messageparsingstuff which does not affect the behaviour
}

根據我的理解,“讀取”方法將盡可能多的字節填充到字節數組中。 限制因素是接收的字節數或數組的大小。

不幸的是,這不是最新發生的事情:我正在傳輸的協議用幾個較小的答案回答我的請求,這些答案是通過同一個套接字連接一個接一個地發送的。

在我的例子中,“read”方法總是返回數組中那些較小答案中的一個。 答案的長度各不相同,但適合陣列的512字節總是足夠的。 這意味着我的數組總是只包含一條消息,而數組的其余/不需要的部分保持不變。

如果我故意定義比我的消息小的字節數組,它將返回幾個完全填充的數組和一個包含剩余字節的最后一個數組,直到消息完成。

(一個100字節的答案,數組長度為30,返回三個完全填充的數組,一個只使用10個字節)

一般來說,InputStream或套接字連接不應該以任何方式解釋傳輸的字節,這就是我現在非常困惑的原因。 我的程序沒有以任何方式知道使用的協議。 事實上,我的整個程序只是這個循環以及建立套接字連接所需的東西。

如果我可以依賴這種行為,那么解析響應非常容易,但由於我不知道是什么原因導致這種行為,我不知道我是否可以指望它。

我正在傳輸的協議是LDAP,但由於我的程序完全沒有意識到這一點,這應該不重要。

根據我的理解,“讀取”方法將盡可能多的字節填充到字節數組中。

你的理解是不正確的。 返回“讀取的字節數”的方法的重點是:它可能返回任何數字。 確切地說:當談論阻塞讀取時 - 當方法返回時,它已經讀取了一些東西 ; 因此它將返回一個> = 1的數字。

換句話說:你永遠不應該依賴read()讀取特定數量的字節。 總是總是檢查返回的數字; 如果你正在等待達到某個值,那么必須在代碼中做一些事情(比如再次緩沖;直到你在自己的緩沖區中得到“足夠”的字節才能繼續)。

事情是:在這種讀取操作中涉及大量的元素。 網絡,操作系統,jvm。 你無法控制到底發生了什么; 因此,您不能也不應該像這樣在代碼中構建任何隱含的假設。

雖然您可能會在給定計算機上看到此行為,尤其是環回,但一旦您開始使用真實網絡並使用不同的硬件,這可能會發生變化。

如果您發送的消息有足夠的延遲,並且足夠快地讀取它們,您將一次看到一條消息。 但是,如果寫入消息足夠接近或者您的閱讀器以任何方式延遲,您可以立即發送多條消息。

此外,如果您的消息足夠大,例如在MTU或更多周圍,即使您的緩沖區足夠大,也可以分解單條消息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM