2016-07-15 28 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