Java NIO服务器
目前我正在研究Java NIO Server(单线程)并遇到了一些问题。 服务器接受传入连接,将初始数据包(数据包包含客户端用于进一步通信的一些数据)写入客户端但不读取它们。 服务器只在我关闭客户端时尝试读取,当然,它返回-1。
在接受连接时,它在以下位置注册:
selectionKey = socketChannel.register(_selector, SelectionKey.OP_READ)
selectionKey.isReadable()
返回false
(应该吗?)
在发送初始数据包之前,操作更改为:
_selectionKey.interestOps(_selectionKey.interestOps() | SelectionKey.OP_WRITE)
发送初始数据包后,操作更改为:
selectedKey.interestOps(selectedKey.interestOps() & ~SelectionKey.OP_WRITE)
数据包被发送。
可能是什么问题呢? 它可以与客户有关吗?
selectionKey.isReadable()
返回false(应该吗?)
当然,直到有数据要读或流结束。
在发送初始数据包之前,操作更改为:
_selectionKey.interestOps(_selectionKey.interestOps() | SelectionKey.OP_WRITE)
馊主意。 OP_WRITE
几乎总是准备好,即除了套接字发送缓冲区已满,所以你只会让你的Selector.select()
方法无意识地旋转。
当你想写入频道时,只需写。 在经典循环中执行此操作:
while (buffer.position() > 0) { buffer.flip(); int count = channel.write(buffer); buffer.compact(); if (count == 0) { // see below ... } }
如果count
为零,则应注册OP_WRITE
,退出循环,然后返回Selector
循环。 如果你没有发生这种循环,请取消注册 OP_WRITE.
请注意,这意味着每个通道都有一个写缓冲区。 由于类似的原因( read()
返回零),每个通道也需要一个读缓冲区。 这又意味着一个包含它们的通道“会话”对象,这可能是通道选择键的附件。
OP_WRITE仅在您想要控制滞后的罕见情况下需要,换句话说,当接收器太慢或发送器太快时。