gpt4 book ai didi

Java NIO : How to know when SocketChannel read() is complete with non-blocking I/O

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:57:15 25 4
gpt4 key购买 nike

我目前正在使用非阻塞 SocketChannel (Java 1.6) 作为 Redis 服务器的客户端。 Redis 直接通过套接字接受纯文本命令,由 CRLF 终止并以类似方式响应,一个简单的例子:

SEND: 'PING\r\n'

RECV: '+PONG\r\n'

Redis 还可以返回大量回复(取决于您的请求),其中包含许多以\r\n 结尾的数据部分,所有这些都作为单个响应的一部分。

我正在使用标准的 while(socket.read() > 0) {//append bytes} 循环从套接字中读取字节并将它们重新组装到客户端回复中。

注意:我没有使用选择器,只是连接到服务器的多个客户端 SocketChannels,等待服务发送/接收命令。

我比较困惑的是SocketChannel.read()方法在非阻塞模式下的contract,具体来说就是如何知道服务器什么时候完成发送,我有完整的消息。

我有几种方法可以防止返回得太快并让服务器有机会回复,但我坚持的一件事是:

  1. 是否有可能 read() 返回字节,然后在后续调用中不返回任何字节,但在另一个后续调用中再次返回一些字节?

基本上,如果我收到至少 1 个字节并且最终 read() 返回 0 那么我知道我已经完成,或者是否有可能,我是否可以相信服务器已完成对我的响应服务器正忙,如果我等待并继续尝试,可能会返回更多字节?

如果即使在 read() 返回 0 字节后(在先前成功读取之后)它可以继续发送字节,那么我不知道如何判断服务器何时完成与我的对话以及-事实上我很困惑 java.io.* 风格的通信甚至会知道服务器何时“完成”。

正如你们所知,读取永远不会返回 -1,除非连接已断开,并且这些是标准的长生命周期数据库连接,因此我不会在每个请求时关闭和打开它们。

我知道一个流行的回应(至少对于这些 NIO 问题)是查看 Grizzly、MINA 或 Netty——如果可能的话,我真的很想在采用一些第 3 方依赖项之前了解这一切在原始状态下是如何工作的.

谢谢。

奖励问题:

我最初认为阻塞 SocketChannel 是解决这个问题的方法,因为我真的不希望调用者做任何事情,直到我处理他们的命令并给他们回复。

如果这最终是一个更好的方法,我有点困惑,只要没有足够的字节来填充给定的缓冲区,就会看到 SocketChannel.read() 阻塞......缺少读取所有字节 -按字节我无法弄清楚这种默认行为实际上是如何使用的...我永远不知道从服务器返回的回复的确切大小,所以我调用了 SocketChannel。 read() 总是阻塞直到超时(此时我终于看到内容位于缓冲区中)。

我不太清楚使用阻塞方法的正确方法,因为它总是在读取时挂起。

最佳答案

查看您的 Redis 规范以获得此答案。

调用 .read() 在一次调用中返回 0 个字节,在后续调用中返回 1 个或多个字节并不违反规则。这是完全合法的。如果有任何事情导致交付延迟,无论是由于网络延迟还是 Redis 服务器缓慢,都可能会发生这种情况。

您寻求的答案与以下问题的答案相同:“如果我手动连接到 Redis 服务器并发送命令,我怎么知道它何时完成向我发送响应以便我可以发送另一个命令? "

答案必须在 Redis 规范中找到。如果服务器在执行完您的命令后没有发送全局 token ,那么这可以在逐个命令的基础上实现。如果 Redis 规范不允许这样做,那么这是 Redis 规范中的错误。他们应该告诉您如何判断他们何时发送了所有数据。这就是 shell 具有命令提示符的原因。 Redis 应该有一个等价物。

如果 Redis 在其规范中没有此功能,那么我建议加入某种计时器功能。对处理套接字的线程进行编码,以在指定时间段(如五秒)内未收到任何数据后发出命令已完成的信号。选择一个明显长于在服务器上执行的最长命令所需的时间。

关于Java NIO : How to know when SocketChannel read() is complete with non-blocking I/O,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4926451/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com