JAVA NIO共定義了四種操作類型:OP_READ、OP_WRITE、OP_CONNECT、OP_ACCEPT,分別對應讀、寫、請求連接、接受連接等網絡Socket操作。ServerSocketChannel和SocketChannel可以註冊自己感興趣的操作類型,當對應操作類型的就緒條件滿足時OS會通知channel,下表描述各種Channel允許註冊的操作類型,Y表示允許註冊,N表示不允許註冊,其中服務器SocketChannel指由服務器ServerSocketChannel.accept()返回的對象。
OP_READ | OP_WRITE | OP_CONNECT | OP_ACCEPT | |
服務器ServerSocketChannel | N | N | N | Y |
服務器SocketChannel | Y | Y | N | N |
客戶端SocketChannel | Y | Y | Y | N |
客戶端請求連接,服務器端接受連接,客戶端與服務器端開始相互發送消息(讀寫),按這個邏輯上表就容易理解。爲了更深入理解,我們可以看看每個操作類型的就緒條件。
操作類型 | 就緒條件及說明 |
OP_READ | 當操作系統讀緩衝區有數據可讀時就緒。並非時刻都有數據可讀,所以一般需要註冊該操作,僅當有就緒時才發起讀操作,有的放矢,避免浪費CPU。 |
OP_WRITE | 當操作系統寫緩衝區有空閒空間時就緒。一般情況下寫緩衝區都有空閒空間,小塊數據直接寫入即可,沒必要註冊該操作類型,否則該條件不斷就緒浪費CPU;但如果是寫密集型的任務,比如文件下載等,緩衝區很可能滿,註冊該操作類型就很有必要,同時注意寫完後取消註冊。 |
OP_CONNECT | 當SocketChannel.connect()請求連接成功後就緒。該操作只給客戶端使用。 |
OP_ACCEPT | 當接收到一個客戶端連接請求時就緒。該操作只給服務器使用。 |
java.nio.channels.SelectionKey類定義了這四種操作類型並提供就緒判斷方法:
public final boolean isReadable() { return (readyOps() & OP_READ) != 0; } public final boolean isWritable() { return (readyOps() & OP_WRITE) != 0; } public final boolean isConnectable() { return (readyOps() & OP_CONNECT) != 0; } public final boolean isAcceptable() { return (readyOps() & OP_ACCEPT) != 0; }