Java NIO:何时在OP_WRITE和OP_READ之间正确切换

时间:2015-06-22 17:19:52

标签: java sockets nio

作为一些背景:

我有一个连接到服务器的SocketChannel,SelectionKey ......等。在客户端,如果我想向服务器发送内容,我只需将数据写入ByteBuffer并通过套接字通道发送。如果所有内容都已写完,我已经完成并可以返回OP_READ。如果不是全部写入,我将剩余的字节存储在某处的“发送”缓冲区中,并在键上标记OP_WRITE(替换OP_READ是一个好主意,所以只能写它吗?)。

因此,下次我调用selectNow()时,我假设它会识别OP_WRITE并尝试刷新更多数据(我将尝试通过输入另一个写入循环来写入数据并重复以前如果需要的话。)

这引出了两个问题:

  • 我是否应该将其保留在OP_WRITE中,直到所有数据都被刷新为止?或者我应该更改为OP_READ并尝试之间的任何读取?

如果写入通道已满并且我无法写入,我是否只是继续循环直到我可以开始写入内容?如果连接突然被阻塞,我不确定我是否应该只写我能做什么,翻回OP_READ,尝试读取,然后翻回OP_WRITE。从我读过的内容来看,这似乎不是正确的做事方式(可能会导致大量开销不断来回切换?)。

  • 当缓冲区可能已满时,处理读取和写入批量数据的最佳方法是什么?

阅读听起来很容易因为你只是循环直到数据被消耗,但写作......服务器可能只是写作而不是阅读。这将为您留下相当完整的发送缓冲区,并且在没有读取的情况下永远在OP_WRITE上循环会很糟糕。你怎么避免这种情况?如果发送缓冲区没有清除,您是否设置了一个只停止尝试写入并再次开始读取的定时器?如果是这样,你会删除OP_WRITE并记住以供日后使用吗?

附带问题:你甚至需要OP_READ来读取网络吗?我不确定它是否像OP_WRITE那样你只在特定的情况下标记它(以防万一我做错了,因为我在OP_READ上有99.9%的时间)。

目前我只是将我的密钥设置为OP_READ,然后将其置于该模式,等待数据,然后转到OP_WRITE,当且仅当写入无法发送所有数据(write()值为0)时。

2 个答案:

答案 0 :(得分:2)

  

我是否应该将其保留在OP_WRITE中,直到所有数据都被刷新为止?或者我应该更改为OP_READ并尝试之间的任何读取?

对此有不同的看法。我的同事应该在他发出新请求之前阅读你发送的回复的每一部分,如果他不这样做,他只是行为不端,而你不应该提前阅读。否则你最终会耗尽内存,你不应该让客户这样做。当然,假设您是请求 - 响应协议中的服务器。其他情况有其自己的要求。

  

如果写入频道已满且无法写入,我是否会继续循环直到我可以开始写东西?

不,你等待OP_WRITE开火。

  

如果连接突然被阻塞,我不确定我是否应该只写我能做什么,翻回OP_READ,尝试读取,然后翻回OP_WRITE。从我读过的内容来看,这似乎不是正确的做事方式(可能会导致大量开销不断来回切换?)。

开销并不重要,但在我上面描述的情况下做错了。

  

当缓冲区可能变满时,处理读取和写入批量数据的最佳方法是什么?

一般情况下,在OP_READ触发时读取;随时写;并使用OP_WRITE告诉您何时出境档位已自行解除。

  

你甚至需要OP_READ来读取网络吗?

是的,否则你只是抽了CPU。

答案 1 :(得分:0)

每当你需要编写只是设置感兴趣的操作(OP_READ || OP_WRITE)。完成编写后,只需将感兴趣的操作设置为OP_READ。

你需要做的就是这些。

相关问题