1

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

一些背景:

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

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

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

现在我的问题:

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

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

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

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

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

  3. read()返回 -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;
}
4

3 回答 3

1

“流”这个词究竟是什么意思?它是从客户端发送的当前消息吗?客户端连接是否有能力发送更多消息?

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

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

如果客户端和服务器之间的连接被重置或中断,就会发生这种情况。你的程序永远不应该假设连接只是存在并且永远不会中断。连接因各种原因而中断,可能是网络组件不稳定,有人拔出了最好留在原处的插头,或者无线网络出现故障。服务器也可能关闭连接,例如,如果服务器程序出现故障、出现错误或连接超时。永远记住,打开的连接是有限的资源,因此如果它们空闲太久,服务器可能会决定关闭它们。

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

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

希望这可以帮助 :)

于 2013-01-04T08:31:04.443 回答
0

“流”这个词到底是什么意思?它是从客户端发送的当前消息吗?

它是字节流,而不是消息。您可以使用这些字节来形成一条消息,但流不知道您正在这样做,它也不以任何方式支持消息。

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

如果另一端关闭它,它只能用 -1 关闭。

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

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

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

于 2013-01-04T08:24:09.023 回答
0
  1. “流”这个词究竟是什么意思?它是从客户端发送的当前消息吗?

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

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

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

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

read()返回 -1 表示对等方正确关闭了连接。'Connection reset by peer' 表示某种协议错误,通常是您已将数据写入已被对等方关闭的连接。

重新输入您的代码,如果read()返回 -1,您必须关闭频道。没有其他明智的方法可以继续。

于 2013-01-04T08:54:21.033 回答