最近一直在忙著JAVA NIO的知識,花了一下午的時間,總算寫出了一個可以運行的程序,廢話少說,上代碼!
Java代碼:
- import?java.io.IOException; ?
- import?java.net.InetSocketAddress; ?
- import?java.net.ServerSocket; ?
- import?java.nio.ByteBuffer; ?
- import?java.nio.channels.SelectionKey; ?
- import?java.nio.channels.Selector; ?
- import?java.nio.channels.ServerSocketChannel; ?
- import?java.nio.channels.SocketChannel; ?
- import?java.util.Iterator; ?
- import?java.util.Set; ?
- ?
- public?class?NIOServer?{ ?
- ???? ?
- ????/*標識數字*/?
- ????private??int?flag?=?0; ?
- ????/*緩沖區大小*/?
- ????private??int?BLOCK?=?4096; ?
- ????/*接受數據緩沖區*/?
- ????private??ByteBuffer?sendbuffer?=?ByteBuffer.allocate(BLOCK); ?
- ????/*發送數據緩沖區*/?
- ????private??ByteBuffer?receivebuffer?=?ByteBuffer.allocate(BLOCK); ?
- ????private??Selector?selector; ?
- ?
- ????public?NIOServer(int?port)?throws?IOException?{ ?
- ????????//?打開服務器套接字通道 ?
- ????????ServerSocketChannel?serverSocketChannel?=?ServerSocketChannel.open(); ?
- ????????//?服務器配置為非阻塞 ?
- ????????serverSocketChannel.configureBlocking(false); ?
- ????????//?檢索與此通道關聯的服務器套接字 ?
- ????????ServerSocket?serverSocket?=?serverSocketChannel.socket(); ?
- ????????//?進行服務的綁定 ?
- ????????serverSocket.bind(new?InetSocketAddress(port)); ?
- ????????//?通過open()方法找到Selector ?
- ????????selector?=?Selector.open(); ?
- ????????//?注冊到selector,等待連接 ?
- ????????serverSocketChannel.register(selector,?SelectionKey.OP_ACCEPT); ?
- ????????System.out.println("Server?Start----8888:"); ?
- ????} ?
- ?
- ?
- ????//?監聽 ?
- ????private?void?listen()?throws?IOException?{ ?
- ????????while?(true)?{ ?
- ????????????//?選擇一組鍵,并且相應的通道已經打開 ?
- ????????????selector.select(); ?
- ????????????//?返回此選擇器的已選擇鍵集。 ?
- ????????????Set<SelectionKey>?selectionKeys?=?selector.selectedKeys(); ?
- ????????????Iterator<SelectionKey>?iterator?=?selectionKeys.iterator(); ?
- ????????????while?(iterator.hasNext())?{???????? ?
- ????????????????SelectionKey?selectionKey?=?iterator.next(); ?
- ????????????????iterator.remove(); ?
- ????????????????handleKey(selectionKey); ?
- ????????????} ?
- ????????} ?
- ????} ?
- ?
- ????//?處理請求 ?
- ????private?void?handleKey(SelectionKey?selectionKey)?throws?IOException?{ ?
- ????????//?接受請求 ?
- ????????ServerSocketChannel?server?=?null; ?
- ????????SocketChannel?client?=?null; ?
- ????????String?receiveText; ?
- ????????String?sendText; ?
- ????????int?count=0; ?
- ????????//?測試此鍵的通道是否已準備好接受新的套接字連接。 ?
- ????????if?(selectionKey.isAcceptable())?{ ?
- ????????????//?返回為之創建此鍵的通道。 ?
- ????????????server?=?(ServerSocketChannel)?selectionKey.channel(); ?
- ????????????//?接受到此通道套接字的連接。 ?
- ????????????//?此方法返回的套接字通道(如果有)將處于阻塞模式。 ?
- ????????????client?=?server.accept(); ?
- ????????????//?配置為非阻塞 ?
- ????????????client.configureBlocking(false); ?
- ????????????//?注冊到selector,等待連接 ?
- ????????????client.register(selector,?SelectionKey.OP_READ); ?
- ????????}?else?if?(selectionKey.isReadable())?{ ?
- ????????????//?返回為之創建此鍵的通道。 ?
- ????????????client?=?(SocketChannel)?selectionKey.channel(); ?
- ????????????//將緩沖區清空以備下次讀取 ?
- ????????????receivebuffer.clear(); ?
- ????????????//讀取服務器發送來的數據到緩沖區中 ?
- ????????????count?=?client.read(receivebuffer);? ?
- ????????????if?(count?>?0)?{ ?
- ????????????????receiveText?=?new?String(?receivebuffer.array(),0,count); ?
- ????????????????System.out.println("服務器端接受客戶端數據--:"+receiveText); ?
- ????????????????client.register(selector,?SelectionKey.OP_WRITE); ?
- ????????????} ?
- ????????}?else?if?(selectionKey.isWritable())?{ ?
- ????????????//將緩沖區清空以備下次寫入 ?
- ????????????sendbuffer.clear(); ?
- ????????????//?返回為之創建此鍵的通道。 ?
- ????????????client?=?(SocketChannel)?selectionKey.channel(); ?
- ????????????sendText="message?from?server--"?+?flag++; ?
- ????????????//向緩沖區中輸入數據 ?
- ????????????sendbuffer.put(sendText.getBytes()); ?
- ?????????????//將緩沖區各標志復位,因為向里面put了數據標志被改變要想從中讀取數據發向服務器,就要復位 ?
- ????????????sendbuffer.flip(); ?
- ????????????//輸出到通道 ?
- ????????????client.write(sendbuffer); ?
- ????????????System.out.println("服務器端向客戶端發送數據--:"+sendText); ?
- ????????????client.register(selector,?SelectionKey.OP_READ); ?
- ????????} ?
- ????} ?
- ?
- ????/** ?
- ?????*?@param?args ?
- ?????*?@throws?IOException ?
- ?????*/?
- ????public?static?void?main(String[]?args)?throws?IOException?{ ?
- ????????//?TODO?Auto-generated?method?stub ?
- ????????int?port?=?8888; ?
- ????????NIOServer?server?=?new?NIOServer(port); ?
- ????????server.listen(); ?
- ????} ?
- }?
Java代碼:
- import?java.io.IOException; ?
- import?java.net.InetSocketAddress; ?
- import?java.nio.ByteBuffer; ?
- import?java.nio.channels.SelectionKey; ?
- import?java.nio.channels.Selector; ?
- import?java.nio.channels.SocketChannel; ?
- import?java.util.Iterator; ?
- import?java.util.Set; ?
- ?
- public?class?NIOClient?{ ?
- ?
- ????/*標識數字*/?
- ????private?static?int?flag?=?0; ?
- ????/*緩沖區大小*/?
- ????private?static?int?BLOCK?=?4096; ?
- ????/*接受數據緩沖區*/?
- ????private?static?ByteBuffer?sendbuffer?=?ByteBuffer.allocate(BLOCK); ?
- ????/*發送數據緩沖區*/?
- ????private?static?ByteBuffer?receivebuffer?=?ByteBuffer.allocate(BLOCK); ?
- ????/*服務器端地址*/?
- ????private?final?static?InetSocketAddress?SERVER_ADDRESS?=?new?InetSocketAddress( ?
- ????????????"localhost",?1111); ?
- ?
- ????public?static?void?main(String[]?args)?throws?IOException?{ ?
- ????????//?TODO?Auto-generated?method?stub ?
- ????????//?打開socket通道 ?
- ????????SocketChannel?socketChannel?=?SocketChannel.open(); ?
- ????????//?設置為非阻塞方式 ?
- ????????socketChannel.configureBlocking(false); ?
- ????????//?打開選擇器 ?
- ????????Selector?selector?=?Selector.open(); ?
- ????????//?注冊連接服務端socket動作 ?
- ????????socketChannel.register(selector,?SelectionKey.OP_CONNECT); ?
- ????????//?連接 ?
- ????????socketChannel.connect(SERVER_ADDRESS); ?
- ????????//?分配緩沖區大小內存 ?
- ???????? ?
- ????????Set<SelectionKey>?selectionKeys; ?
- ????????Iterator<SelectionKey>?iterator; ?
- ????????SelectionKey?selectionKey; ?
- ????????SocketChannel?client; ?
- ????????String?receiveText; ?
- ????????String?sendText; ?
- ????????int?count=0; ?
- ?
- ????????while?(true)?{ ?
- ????????????//選擇一組鍵,其相應的通道已為?I/O?操作準備就緒。 ?
- ????????????//此方法執行處于阻塞模式的選擇操作。 ?
- ????????????selector.select(); ?
- ????????????//返回此選擇器的已選擇鍵集。 ?
- ????????????selectionKeys?=?selector.selectedKeys(); ?
- ????????????//System.out.println(selectionKeys.size()); ?
- ????????????iterator?=?selectionKeys.iterator(); ?
- ????????????while?(iterator.hasNext())?{ ?
- ????????????????selectionKey?=?iterator.next(); ?
- ????????????????if?(selectionKey.isConnectable())?{ ?
- ????????????????????System.out.println("client?connect"); ?
- ????????????????????client?=?(SocketChannel)?selectionKey.channel(); ?
- ????????????????????//?判斷此通道上是否正在進行連接操作。 ?
- ????????????????????//?完成套接字通道的連接過程。 ?
- ????????????????????if?(client.isConnectionPending())?{ ?
- ????????????????????????client.finishConnect(); ?
- ????????????????????????System.out.println("完成連接!"); ?
- ????????????????????????sendbuffer.clear(); ?
- ????????????????????????sendbuffer.put("Hello,Server".getBytes()); ?
- ????????????????????????sendbuffer.flip(); ?
- ????????????????????????client.write(sendbuffer); ?
- ????????????????????} ?
- ????????????????????client.register(selector,?SelectionKey.OP_READ); ?
- ????????????????}?else?if?(selectionKey.isReadable())?{ ?
- ????????????????????client?=?(SocketChannel)?selectionKey.channel(); ?
- ????????????????????//將緩沖區清空以備下次讀取 ?
- ????????????????????receivebuffer.clear(); ?
- ????????????????????//讀取服務器發送來的數據到緩沖區中 ?
- ????????????????????count=client.read(receivebuffer); ?
- ????????????????????if(count>0){ ?
- ????????????????????????receiveText?=?new?String(?receivebuffer.array(),0,count); ?
- ????????????????????????System.out.println("客戶端接受服務器端數據--:"+receiveText); ?
- ????????????????????????client.register(selector,?SelectionKey.OP_WRITE); ?
- ????????????????????} ?
- ?
- ????????????????}?else?if?(selectionKey.isWritable())?{ ?
- ????????????????????sendbuffer.clear(); ?
- ????????????????????client?=?(SocketChannel)?selectionKey.channel(); ?
- ????????????????????sendText?=?"message?from?client--"?+?(flag++); ?
- ????????????????????sendbuffer.put(sendText.getBytes()); ?
- ?????????????????????//將緩沖區各標志復位,因為向里面put了數據標志被改變要想從中讀取數據發向服務器,就要復位 ?
- ????????????????????sendbuffer.flip(); ?
- ????????????????????client.write(sendbuffer); ?
- ????????????????????System.out.println("客戶端向服務器端發送數據--:"+sendText); ?
- ????????????????????client.register(selector,?SelectionKey.OP_READ); ?
- ????????????????} ?
- ????????????} ?
- ????????????selectionKeys.clear(); ?
- ????????} ?
- ????} ?
- }?
個人感覺,JAVA NIO的操作時麻煩了不少,但是無疑這樣做效率會得到很大的提升。