2016-07-15 49 views
1

在Java NIO使用Selector的规范的方法是:NIO事件注册的顺序是否正确?

  1. REGIST的一个ServerSocketChannelSelectionKey.OP_ACCEPT事件类型。
  2. 调用select方法(它阻塞线程)在一个循环方法
  3. 然后当OP_ACCEPT事件发生,相对AcceptEventHandler被调用以接受一个SocketChannel
  4. 然后与SelectionKey.OP_READ事件类型REGIST接受SocketChannel
  5. 当发生读取事件时,ReadEventHandler处理输入,然后用SelectionKey.OP_WRITE事件类型注册SocketChannel

我的问题是,为什么不在开始时一次注册三种事件类型?序列是否有意义?

+0

它取决于协议,但通常(图片HTTP服务器),你不会一次注册它们,因为你会被告知你可以在读取任何东西之前写入套接字,并且没有任何东西写,你会不断收到通知。 –

回答

1

在Java NIO使用Selector的典型方式是:

不,它不是。见下文。

为什么一开始不要立即注册三种事件类型?

因为你不行。在拨打accept()之前,您没有接受的频道,直到您注册了OP_ACCEPT并将其激活为止,您才会这样做,并且只有拥有该频道后才能注册已接受的频道。

序列是否有意义?

没有其他会有意义。

注意,在您遇到短或长度为零的写入之前,您不会注册OP_WRITE。原因在于它几乎总是准备好,所以这个策略只是在你需要写入内容时编写,并且只使用OP_WRITE告诉你什么时候可以在短的写入后再次写入(这意味着套接字发送缓冲区是充分)。

+0

Tks man,你解释得很清楚,OP_READ和OP_WRITE在Selector上用SocketChannel注册,在我接受操作之前我不能拥有它... – JasonHuang

1

我将尝试在对话中添加一些内容。

A ServerSocketChannel只能新建连接accept()OP_READ/OP_WRITE不会为你做任何事情。我很确定你可以添加他们,但他们只会被忽略,因为ServerSocketChannel's唯一的责任是accept()远程SocketChannel

一旦你accept()并得到一个新的SocketChannel;你首先要听OP_READ。如果您收听OP_WRITE,那么很可能您每次拨打select()时都会收到OP_WRITE,这会消耗大量资源。

当您试图将一些数据写入SocketChannel并且没有写入所有数据时,您只想收听OP_WRITE