簡體   English   中英

Java Nio read()返回-1

[英]Java nio read() return -1

這不是我第一次嘗試了解這個問題,但我希望它將是最后一個:

一些背景:

我有一個以非阻塞模式工作的Java SocketChannel NIO服務器。

該服務器具有多個客戶端,可以從該客戶端發送和接收消息。

每個客戶端每隔一段時間就會通過"keepalive"消息維護其與服務器的連接。 服務器的主要思想是客戶端將始終保持連接,並以“推送”模式從中接收消息。

現在我的問題是:

在Java NIO中, read()函數-當read()返回-1時-表示其EOS。

這里我提出的問題中我意識到這意味着套接字已完成其當前流,不需要關閉。

當在谷歌搜索更多有關此的時候,我發現這確實意味着該連接在另一側是關閉的。

  1. “流”一詞到底是什么意思? 是客戶端發送的當前消息嗎? 客戶端連接是否可以發送更多消息?

  2. 如果客戶端從未告訴過SocketChannel為什么它會在客戶端關閉SocketChannel

  3. read() return -1和對等I / O錯誤重置連接有什么區別?

這是我從SocketChannel讀取的方式:

private JSONObject readIncomingData(SocketChannel socketChannel)
        throws JSONException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, IOException {
    JSONObject returnObject = null;
    ByteBuffer buffer = ByteBuffer.allocate(1024);
    Charset charset = Charset.forName("UTF-8");
    String endOfMesesage = "\"}";
    String message = "";
    StringBuilder input = new StringBuilder();      
    boolean continueReading = true;
    while (continueReading && socketChannel.isOpen()) 
    {
        buffer.clear();         
        int bytesRead = socketChannel.read(buffer);             
        if (bytesRead == -1)
        {
            continueReading = false;                    
            continue;
        }
        buffer.flip();
        input.append(charset.decode(buffer));
        message = input.toString();
        if (message.contains(endOfMesesage))
            continueReading = false;
    }       
    if (input.length() > 0 && message.contains(endOfMesesage))
    {
        JSONObject messageJson = new JSONObject(input.toString());
        returnObject = new JSONObject(encrypter.decrypt(messageJson.getString("m")));
    }           
    return returnObject;
}

“流”一詞到底是什么意思? 是客戶端發送的當前消息嗎? 客戶端連接是否可以發送更多消息?

流意味着在兩個位置之間(通常在客戶端和服務器之間)流動的數據,但是實際上,它是任何類型的數據流動。 例如,如果您從硬盤上讀取文件,則使用FileInputStream,它表示從磁盤上的文件流到程序的數據。 這是一個非常籠統的概念。 可以將其視為一條河流,那里的水就是數據。 另外,它是一條非常酷的河流,可讓您控制水/數據的流動方式。

如果客戶端從未告訴過SocketChannel,為什么它會在客戶端關閉SocketChannel?

如果客戶端和服務器之間的連接被重置或中斷,則可能發生這種情況。 您的程序永遠不要以為連接是實時的,並且永遠不會中斷。 由於各種原因,連接可能會中斷,這可能是不穩定的網絡組件,有人拔了插頭,最好將插頭留在原處,或者無線網絡出現故障。 另外,服務器可能會關閉連接,例如,如果服務器程序出現故障,出現錯誤或連接超時。 始終記住,打開的連接是有限的資源,因此如果服務器空閑時間過長,服務器可能會決定關閉它們。

read()return -1和對等I / O錯誤重置連接有什么區別?

當read()返回-1時,這僅表示當前流中沒有更多數據。 連接重置意味着可能有更多數據,但是該連接不再存在,因此無法再讀取該數據。 再次對河流進行分析:將數據想象為使用連接兩個村庄(連接)的河床從上游村庄(又名Serverville)向下游村庄(又名Clientville)發送的水。 現在,Serverville的某個人發揮了重要作用,水(數據)從Serverville流到Clientville。 Serverville已發送完所有要發送的水后,它將關閉杠桿,河床將再次變空(並在連接關閉時實際上被銷毀了)。 這是Clientville獲得-1的地方。 現在想象一下,一些推土機打斷了河床,而有些水卻從未流到Clientville。 這是“連接重置”情況。

希望這可以幫助 :)

“流”一詞到底是什么意思? 是客戶端發送的當前消息嗎?

它是字節流,而不是消息。 您可以使用這些字節來形成消息,但是流不知道您正在執行此操作,也不以任何方式支持消息。

如果客戶端從未告訴過SocketChannel,為什么它會在客戶端關閉SocketChannel?

如果另一端將其關閉,則只能以-1關閉它。

read()return -1和對等I / O錯誤重置連接有什么區別?

您可以通過其他方式關閉或斷開連接,例如從同一側將其關閉,或者連接超時(例如,拔出網絡電纜)。

順便說一句:您編寫代碼的方式更適合於阻止NIO。 例如,如果您收到一條以上的完整消息,則丟棄第一條消息之后的所有內容。 如果使用阻塞IO並保留所有已閱讀內容,則不會損壞或丟棄消息。

  1. “流”一詞到底是什么意思? 是客戶端發送的當前消息嗎?

它基本上意味着連接的一側,即全雙工。 TCP是字節流協議,提供兩個獨立的字節流,每個方向一個。

  1. 如果客戶端從未告訴過SocketChannel,為什么它會在客戶端關閉?

不會的。 客戶端確實關閉了連接。 這就是read()返回-1的意思。

read()return -1和對等I / O錯誤重置連接有什么區別?

read()返回-1表示對等方正確關閉了連接。 “由對等方重置連接”表示某種協議錯誤,通常是您已將數據寫入到已被對等方關閉的連接中。

重新編寫代碼,如果read()返回-1,則必須關閉通道。 沒有其他明智的方法可以進行。

暫無
暫無

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

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