这不是我第一次尝试理解这个问题,但我希望它会是最后一个:
一些背景:
我有一个Java SocketChannel NIO
服务器在非阻塞模式下工作。
此服务器有多个客户端,可以从中发送和接收消息。
每个客户端每隔一段时间就会使用"keepalive"
消息与服务器保持连接。
服务器的主要思想是客户端将“始终”保持连接状态,并以“推送”模式从客户端接收消息。
现在问我的问题:
在Java NIO read()
函数中 - 当read()返回-1时 - 表示它的EOS。
在我问here的问题中,我意识到这意味着套接字已经完成了当前的流而不需要关闭..
在谷歌搜索更多关于这一点时,我发现它确实意味着连接在另一边关闭..
“流”这个词究竟意味着什么?它是从客户端发送的当前消息吗?客户端连接是否能够再发送消息?
如果客户从未告诉他关闭,为什么会在客户端关闭SocketChannel
?
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;
}
答案 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)
- “流”这个词究竟意味着什么?它是从客户端发送的当前消息吗?
醇>
它基本上意味着连接的一端,即全双工。 TCP是一种字节流协议,提供两个独立的字节流,每个方向一个。
- 如果客户端从不告诉他关闭,为什么SocketChannel会在客户端被关闭?
醇>
不会。客户端确实关闭了连接。这就是read()
返回-1的含义。
read()返回-1和通过对等I / O错误重置连接之间的区别是什么?
read()
返回-1表示对等方正确关闭了连接。 “通过对等方重置连接”表示某种协议错误,通常是您已将数据写入已由对等方关闭的连接。
重新编写代码,如果read()
返回-1,则必须关闭该频道。没有其他合理的方法可以继续。