SocketChannel vs. ServerSocketChannel
- 父類:SelectableChannel。Channel表現了一個可以進行IO操作的通道(比如,通過FileChannel,我們可以對文件進行讀寫操作)
- ServerSocketChannel主要用在Server中,用於接收客戶端的鏈接請求
SocketChannel則用於真正的讀寫數據,同時還可以用於客戶端發送鏈接請求。 - 真正實現讀寫數據操作的就是這些SocketChannel,上面的ServerSocketChannel只是負責接收連接請求。
- 以下均簡稱為channel
channel vs. Selector
- channel需要注冊到selector上。channel可以注冊到一個或多個Selector上以進行異步IO操作。
channel.register(selector, SelectionKey.OP_ACCEPT);
channel.register(selector, xxx, object); //attachment被存放在返回的SelectionKey中
channel.keyFor(selector); //返回該channe在Selector上的注冊關系所對應的SelectionKey。若無注冊關系,返回null。
- Selector可以同時監控多個SelectableChannel的IO狀況,是異步IO的核心。
Selector.open(); //靜態方法,創建一個selector實例
selector.select(); //selector通過調用select(),將注冊的channel中有事件發生的取出來進行處理。監控所有注冊的channel,當其中有注冊的IO操作可以進行時,該函數返回,並將對應的SelectionKey加入selected-key set。
selector.keys(); //所有注冊在這個Selector上的channel
selector.selectedKeys(); //所有通過select()方法監測到可以進行IO操作的channel
SelectionKey
- 代表了Selector和SelectableChannel的注冊關系
key.attachment(); //返回SelectionKey的attachment,attachment可以在注冊channel的時候指定。
key.channel(); // 返回該SelectionKey對應的channel。
key.selector(); // 返回該SelectionKey對應的Selector。
key.interestOps(); //返回代表需要Selector監控的IO操作的bit mask
key.readyOps(); //返回一個bit mask,代表在相應channel上可以進行的IO操作。
Demo1: Server端底層如何接受連接
| int n = selector.select(); // 得到selector所捕獲的事件數量 //一個key被處理完成后,就都被從就緒關鍵字(ready keys)列表中除去 sc.configureBlocking(false); // 設置SocketChannel為非阻塞方式 |
Demo2: Server端底層如何讀取channel上的數據
| SelectionKey s = (SelectionKey) i.next(); // 對事件一一處理 //一個key被處理完成后,就都被從就緒關鍵字(ready keys)列表中除去 |
Demo3: Client端底層如何發起連接、寫入數據
| InetSocketAddress addr = new InetSocketAddress(host,port); if(sc.finishConnect()){ // 當連接成功時,執行相應操作 |
學習文檔:
http://www.iteye.com/topic/40489
http://blog.csdn.net/derekjiang/article/details/4465697
http://blog.csdn.net/derekjiang/article/details/4470175
http://www.cnblogs.com/freedom-elf/archive/2011/08/11/2135015.html
