天天看點

NIO模式例子

NIO模式主要優勢是展現在對多連接配接的管理,對衆多連接配接各種事件的轉發讓處理變得更加高效,是以一般是伺服器端才會使用NIO模式,而對于用戶端為了友善及習慣使用阻塞模式的Socket進行通信。是以NIO模式的例子也僅僅看下服務端的實作即可。

public class NioServer {

private ByteBuffer readBuffer;

private Selector selector;

private void init() {

readBuffer = ByteBuffer.allocate(1024);

ServerSocketChannel servSocketChannel;

try {

servSocketChannel = ServerSocketChannel.open();

servSocketChannel.configureBlocking(false);

servSocketChannel.socket().bind(new InetSocketAddress(8888));

selector = Selector.open();

servSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

} catch (IOException e) {

e.printStackTrace();

}

private void listen() {

while (true) {

selector.select();

Iterator ite = selector.selectedKeys().iterator();

while (ite.hasNext()) {

SelectionKey key = (SelectionKey) ite.next();

ite.remove();

handleKey(key);

} catch (Throwable t) {

t.printStackTrace();

private void handleKey(SelectionKey key) throws IOException,ClosedChannelException {

SocketChannel channel = null;

if (key.isAcceptable()) {

ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();

channel = serverChannel.accept();

channel.configureBlocking(false);

channel.register(selector, SelectionKey.OP_READ);

} else if (key.isReadable()) {

channel = (SocketChannel) key.channel();

readBuffer.clear();

int count = channel.read(readBuffer);

if (count > 0) {

readBuffer.flip();

ByteBuffer response = ByteBuffer.wrap(new byte[] { 'r','e', 's', 'p', 'o', 'n', 's', 'e' });

byte[] request=new byte[7];

System.out.println(readBuffer.get(request));

while (response.hasRemaining()) {

    channel.write(response);

} else {

channel.close();

if (channel != null) {

public static void main(String[] args) {

NioServer nioServer = new NioServer();

nioServer.init();

nioServer.listen();

初始化方法主要做的事情包括配置設定讀緩沖、開啟一個ServerSocketChannel通道并設定為非阻塞、綁定8888端口、開啟一個選擇器Selector、将ServerSocketChannel對象以OP_ACCEPT作為感興趣事件注冊到選擇器中。

監聽方法主要做的事情是不斷通過選擇器select出感興趣的事件,再将對應的key送到handleKey方法處理,分三種事件說明,①OP_ACCEPT事件,一個用戶端連接配接連進來最開始會觸發一個接收事件,此時要通過調用ServerSocketChannel對象的accept将用戶端連接配接接收,并将接收到的用戶端channel設定為非阻塞,最後将用戶端channel以OP_READ事件注冊到選擇器中;②OP_READ事件,假如用戶端連接配接寫入“request”字元串,服務端選擇器選擇出該通道有字元串待讀,從key中擷取對應channel并執行read操作,這裡會輸出“request”字元串,然後向用戶端輸出“response”字元串;③OP_WRITE事件,這裡為友善并沒有注冊寫事件而是直接将位元組串寫回用戶端,實際進行中可以這樣:先嘗試直接往通道寫入,在網絡阻塞時即循環寫入資料寫不了時則注冊OP_WRITE事件避免線程阻塞,交給後面選擇器select後再次進行寫處理。

非阻塞模式提供了另外一種IO處理模型,把阻塞操作改成非阻塞操作,增加了程式編寫的難度,但如果要寫出高性能高并發的服務端服務則必須掌握NIO模式。

========廣告時間========鄙人的新書《Tomcat核心設計剖析》已經在京東銷售了,有需要的朋友可以到 https://item.jd.com/12185360.html 進行預定。感謝各位朋友。[為什麼寫《Tomcat核心設計剖析》](http://blog.csdn.net/wangyangzhizhou/article/details/74080321)=========================歡迎關注:![這裡寫圖檔描述](http://img.blog.csdn.net/20170509102539658?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2FuZ3lhbmd6aGl6aG91/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)

繼續閱讀