Java nio read()返回-1

时间:2013-01-04 08:16:50

标签: java nio socketchannel

这不是我第一次尝试理解这个问题,但我希望它会是最后一个:

一些背景:

我有一个Java SocketChannel NIO服务器在非阻塞模式下工作。

此服务器有多个客户端,可以从中发送和接收消息。

每个客户端每隔一段时间就会使用"keepalive"消息与服务器保持连接。 服务器的主要思想是客户端将“始终”保持连接状态,并以“推送”模式从客户端接收消息。

现在问我的问题:

在Java NIO read()函数中 - 当read()返回-1时 - 表示它的EOS。

在我问here的问题中,我意识到这意味着套接字已经完成了当前的流而不需要关闭..

在谷歌搜索更多关于这一点时,我发现它确实意味着连接在另一边关闭..

  1. “流”这个词究竟意味着什么?它是从客户端发送的当前消息吗?客户端连接是否能够再发送消息?

  2. 如果客户从未告诉他关闭,为什么会在客户端关闭SocketChannel

  3. read()返回-1和通过对等I / O错误重置连接之间有什么区别?

  4. 这是我从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;
    }
    

3 个答案:

答案 0 :(得分:1)

“流”这个词究竟意味着什么?它是从客户端发送的当前消息吗?客户端连接是否能够再发送消息?

流意味着在两个位置之间流动的数据,通常在客户端和服务器之间,但实际上它是任何类型的数据流。例如。如果您从硬盘中读取文件,则使用FileInputStream表示从光盘上的文件流向程序的数据。这是一个非常通用的概念。把它想象成一条河流,水就是数据。此外,它是一种非常酷的河流,可以让您控制水/数据的流动方式。

如果客户端从未告诉过他,那么为什么SocketChannel会在客户端被关闭?

如果客户端和服务器之间的连接被重置或中断,则会发生这种情况。您的程序永远不应该假设连接只是存在且永远不会中断。连接因各种原因而中断,可能是一个片状的网络组件,有人拔出的插头应该更好地留在原地或无线网络正在崩溃。服务器也可以关闭连接,例如如果服务器程序出现故障,有错误或连接进入超时状态。永远记住,开放连接是一种有限的资源,因此如果服务器空闲时间过长,服务器可能会决定关闭它们。

read()返回-1和通过对等I / O错误重置连接之间有什么区别?

当read()返回-1时,这意味着流中当前没有更多数据。连接重置意味着可能有更多数据,但连接不再存在,因此无法再读取此数据。再次采取河流厌倦:将数据视为从上游村庄(又名Serverville)向连接两个村庄(连接)的河床发送到下游村庄(又名Clientville)的一定数量的水。现在Serverville的某个人拉出了大杠杆,水(数据)从Serverville流向Clientville。在Serverville发送了它想要发送的所有水之后,它关闭了杠杆并且河床将再次变空(并且在连接关闭时实际上被破坏)。这就是Clientville获得-1的地方。现在想象一些推土机打断了河床,一些水从未进入Clientville。这是“连接重置”的情况。

希望这会有所帮助:)

答案 1 :(得分:0)

  

“流”这个词究竟意味着什么?它是从客户端发送的当前消息吗?

这是一个字节流,而不是消息。您可以使用这些字节来形成消息,但流不知道您正在执行此操作,也不以任何方式支持消息。

  

如果客户端从未告诉他关闭,为什么会在客户端关闭SocketChannel?

如果另一端关闭它,它只能以-1结束。

  

read()返回-1和对等I / O错误连接重置之间有什么区别?

您可以通过其他方式关闭或断开连接,例如从同一侧关闭连接,或连接中的超时,例如您拔出网线。

顺便说一句:你编写代码的方式更适合阻止NIO。例如,如果您收到多条完整邮件,则会丢弃第一条邮件之后的所有邮件。如果您使用阻止IO并保留您阅读的所有内容,则不会损坏或丢弃消息。

答案 2 :(得分:0)

  
      
  1. “流”这个词究竟意味着什么?它是从客户端发送的当前消息吗?
  2.   

它基本上意味着连接的一端,即全双工。 TCP是一种字节流协议,提供两个独立的字节流,每个方向一个。

  
      
  1. 如果客户端从不告诉他关闭,为什么SocketChannel会在客户端被关闭?
  2.   

不会。客户端确实关闭了连接。这就是read()返回-1的含义。

  

read()返回-1和通过对等I / O错误重置连接之间的区别是什么?

read()返回-1表示对等方正确关闭了连接。 “通过对等方重置连接”表示某种协议错误,通常是您已将数据写入已由对等方关闭的连接。

重新编写代码,如果read()返回-1,则必须关闭该频道。没有其他合理的方法可以继续。