繁体   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