JAVA NIO 实例
生活随笔
收集整理的這篇文章主要介紹了
JAVA NIO 实例
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
為什么80%的碼農都做不了架構師?>>> ??
JAVA NIO的服務器端實現(xiàn)
package com.flyer.cn.javaIO;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.nio.charset.Charset; import java.util.Date; import java.util.Iterator; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;public class EchoServer {public static SelectorLoop connectionBell;public static SelectorLoop readBell;public boolean isReadBellRunning=false;private ExecutorService thdPool=Executors.newCachedThreadPool();public static void main(String[] args) throws IOException {new EchoServer().startServer();}// 啟動服務器public void startServer() throws IOException {// 準備好一個鬧鐘.當有鏈接進來的時候響.connectionBell = new SelectorLoop();// 準備好一個鬧裝,當有read事件進來的時候響.readBell = new SelectorLoop();// 開啟一個server channel來監(jiān)聽ServerSocketChannel ssc = ServerSocketChannel.open();// 開啟非阻塞模式ssc.configureBlocking(false);ServerSocket socket = ssc.socket();socket.bind(new InetSocketAddress("localhost",7878));// 給鬧鐘規(guī)定好要監(jiān)聽報告的事件,這個鬧鐘只監(jiān)聽新連接事件.ssc.register(connectionBell.getSelector(), SelectionKey.OP_ACCEPT);new Thread(connectionBell,"connectionBell").start();}// Selector輪詢線程類public class SelectorLoop implements Runnable {private Selector selector;private ByteBuffer temp = ByteBuffer.allocate(1024);public SelectorLoop() throws IOException {this.selector = Selector.open();}public Selector getSelector() {return this.selector;}@Overridepublic void run() {while(true) {try {// 阻塞,只有當至少一個注冊的事件發(fā)生的時候才會繼續(xù).this.selector.select();Set<SelectionKey> selectKeys = this.selector.selectedKeys();Iterator<SelectionKey> it = selectKeys.iterator();while (it.hasNext()) {SelectionKey key = it.next();it.remove();if (key.isAcceptable()) {// 這是一個connection accept事件, 并且這個事件是注冊在serversocketchannel上的.ServerSocketChannel ssc = (ServerSocketChannel) key.channel();// 接受一個連接.SocketChannel sc = ssc.accept();// 對新的連接的channel注冊read事件. 使用readBell鬧鐘.sc.configureBlocking(false);sc.register(readBell.getSelector(), SelectionKey.OP_READ);// 如果讀取線程還沒有啟動,那就啟動一個讀取線程.synchronized(EchoServer.this) {if (!EchoServer.this.isReadBellRunning) {EchoServer.this.isReadBellRunning = true;new Thread(readBell,"readBell").start();}}} else if (key.isReadable()){// 這是一個read事件,并且這個事件是注冊在socketchannel上的.SocketChannel sc = (SocketChannel) key.channel();// 寫數(shù)據(jù)到bufferint count = sc.read(temp);if (count < 0) {// 客戶端已經(jīng)斷開連接.key.cancel();sc.close();return;}// 切換buffer到讀狀態(tài),內部指針歸位.temp.flip();String msg = Charset.forName("UTF-8").decode(temp).toString();System.out.println(new Date().toLocaleString()+"Server received ["+msg+"] from client address:" + sc.getRemoteAddress());// 清空buffertemp.clear();thdPool.submit(new Dispatch(sc,msg));}}} catch (IOException e) {e.printStackTrace();}}}public class Dispatch implements Runnable{private SocketChannel sc;private String msg;public Dispatch(SocketChannel _sc,String _msg){this.sc=_sc;this.msg=_msg;}public void run() {try{Thread.sleep(1000);// echo back.sc.write(ByteBuffer.wrap(msg.getBytes(Charset.forName("UTF-8"))));}catch(Exception ex){ex.printStackTrace();}}}}}JAVA NIO的客戶端實現(xiàn)
package com.flyer.cn.javaIO;import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.ClosedChannelException; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.SocketChannel; import java.nio.charset.Charset; import java.util.Date; import java.util.Iterator; import java.util.Set;public class Client implements Runnable {// 空閑計數(shù)器,如果空閑超過10次,將檢測server是否中斷連接.private String clientName;private static int idleCounter = 0;private Selector selector;private SocketChannel socketChannel;private ByteBuffer temp = ByteBuffer.allocate(1024);public static void main(String[] args) throws IOException {for(int i=0;i<100;i++){Client client= new Client("client"+i);new Thread(client).start();//client.sendFirstMsg();}}public Client(String name) throws IOException {this.clientName=name;// 同樣的,注冊鬧鐘.this.selector = Selector.open();// 連接遠程serversocketChannel = SocketChannel.open();// 如果快速的建立了連接,返回true.如果沒有建立,則返回false,并在連接后出發(fā)Connect事件.Boolean isConnected = socketChannel.connect(new InetSocketAddress("localhost", 7878));socketChannel.configureBlocking(false);SelectionKey key = socketChannel.register(selector, SelectionKey.OP_READ);if (isConnected) {this.sendFirstMsg();} else {// 如果連接還在嘗試中,則注冊connect事件的監(jiān)聽. connect成功以后會出發(fā)connect事件.key.interestOps(SelectionKey.OP_CONNECT);}}public void sendFirstMsg() throws IOException {String msg = "Hello NIO.From "+this.clientName;socketChannel.write(ByteBuffer.wrap(msg.getBytes(Charset.forName("UTF-8"))));}@Overridepublic void run() {while (true) {try {// 阻塞,等待事件發(fā)生,或者1秒超時. num為發(fā)生事件的數(shù)量.int num = this.selector.select(1000);if (num ==0) {idleCounter ++;if(idleCounter >10) {// 如果server斷開了連接,發(fā)送消息將失敗.try {this.sendFirstMsg();} catch(ClosedChannelException e) {e.printStackTrace();this.socketChannel.close();return;}}continue;} else {idleCounter = 0;}Set<SelectionKey> keys = this.selector.selectedKeys();Iterator<SelectionKey> it = keys.iterator();while (it.hasNext()) {SelectionKey key = it.next();it.remove();if (key.isConnectable()) {// socket connectedSocketChannel sc = (SocketChannel)key.channel();if (sc.isConnectionPending()) {sc.finishConnect();}// send first message;this.sendFirstMsg();}if (key.isReadable()) {// msg received.SocketChannel sc = (SocketChannel)key.channel();this.temp = ByteBuffer.allocate(1024);int count = sc.read(temp);if (count<0) {sc.close();continue;}// 切換buffer到讀狀態(tài),內部指針歸位.temp.flip();String msg = Charset.forName("UTF-8").decode(temp).toString();System.out.println("Client received ["+msg+"] from server address:" + sc.getRemoteAddress()+new Date().toLocaleString());Thread.sleep(1000);// echo back.sc.write(ByteBuffer.wrap(msg.getBytes(Charset.forName("UTF-8"))));// 清空buffertemp.clear();}}} catch (IOException e) {e.printStackTrace();} catch (InterruptedException e) {e.printStackTrace();}}}}這個實例在高并發(fā)下會產(chǎn)生粘包和段包的問題,解決方法參考下一篇
轉載于:https://my.oschina.net/u/1774673/blog/808085
總結
以上是生活随笔為你收集整理的JAVA NIO 实例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《HTTPS权威指南》- SSL、TLS
- 下一篇: 投票系统的前台实现