Java nio read() 返回-1

标签 java nio socketchannel

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

一些背景:

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

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

每个客户端每隔一段时间就会通过“keepalive”消息来维护与服务器的连接。 服务器的主要思想是客户端将“始终”保持连接并以“推送”模式接收来自服务器的消息。

现在回答我的问题:

在 Java NIO read() 函数中 - 当 read() 返回 -1 时 - 这意味着它是 EOS。

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

当在谷歌中搜索更多相关内容时,我发现这确实意味着另一端的连接已关闭..

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

  2. 如果客户端从未告诉他关闭,为什么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() 返回 -1 和对等 I/O 错误导致连接重置之间有什么区别?

当 read() 返回 -1 时,这仅意味着流中当前没有更多数据。连接重置意味着可能还有更多数据,但连接不再存在,因此无法再读取该数据。再次采用河流类比:将数据视为使用连接两个村庄(连接)的河床从上游村庄(又名 Serverville)发送到下游村庄(又名 Clientville)的一定量的水。现在,Serverville 的某个人拉动了大杠杆,水(数据)从 Serverville 流向 Clientville。 Serverville 发送完所有想要发送的水后,它会关闭控制杆,河床将再次变空(并且实际上随着连接关闭而被破坏)。这就是 Clientville 得到 -1 的地方。现在想象一下,一些推土机破坏了河床,一些水从未到达克伦特维尔。这就是“连接重置”的情况。

希望这有帮助:)

关于Java nio read() 返回-1,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14153488/

相关文章:

java - 读取bin文件并将内容发送到jni

java - 服务器关闭时关闭选择器

java - 避免 Java 8 Files.walk(..) 终止原因 ( java.nio.file.AccessDeniedException )

Java NIO 问题/对 isReadable 工作方式的误解

java - java中的TreeSet无法正确显示数据

java - 基于空间主体建模的数据结构

Java IO vs NIO,真正的区别是什么?

java - 管理客户端套接字池

从未选择用于多个 OP 代码的 Java SocketChannel register()

java - Cron 无法使用分钟