Java傳統IO / NIO基礎知識
阿新 • • 發佈:2018-12-15
1.IO的基本操作
只執行緒情況下只能有一個客戶端的連線
package xss.netty.basicio; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; /** * java 原生的IO處理方式 * IO Server */ public class IOMainServerTest { public static void main(String[] args) throws Exception { ServerSocket serverSocket=new ServerSocket(9999); System.out.println("server start......."); while (true){ // 會阻塞client的連線,只到client的訊息處理完 //也就是說一次只能處理一個客戶端的請求 Socket socket=serverSocket.accept(); System.out.println("new client connect"); handler(socket); } } public static void handler(Socket socket) { try{ InputStream inputStream=socket.getInputStream(); byte[] readBytes=new byte[1024]; while(true){ int reads =inputStream.read(readBytes);//阻塞資料的讀取 if(reads != -1){ System.out.println("message ->"+new String(readBytes,0,reads)); }else{ break; } } }catch (Exception ex){ ex.printStackTrace(); }finally { try { System.out.println("socket closed."); socket.close(); } catch (IOException e) { e.printStackTrace(); } } } }
可多客戶端的同時連線
package xss.netty.basicio; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * java 原生的IO處理方式 * 改進之一:服務端可以同時接收多個客戶端的請求 * */ public class IOMainServerMutliClientTest { public static void main(String[] args) throws Exception { ServerSocket serverSocket=new ServerSocket(9999); System.out.println("server start......."); ExecutorService executors= Executors.newCachedThreadPool(); while (true){ // 會阻塞client的連線,只到client的訊息處理完 //也就是說一次只能處理一個客戶端的請求 final Socket socket=serverSocket.accept(); System.out.println("new client connect"); executors.execute(new Runnable() { public void run() { handler(socket); } }); } } public static void handler(Socket socket) { try{ InputStream inputStream=socket.getInputStream(); byte[] readBytes=new byte[1024]; while(true){ int reads =inputStream.read(readBytes);//阻塞資料的讀取 if(reads != -1){ System.out.println("message ->"+new String(readBytes,0,reads)); }else{ break; } } }catch (Exception ex){ ex.printStackTrace(); }finally { try { System.out.println("socket closed."); socket.close(); } catch (IOException e) { e.printStackTrace(); } } } }
2.NIO的基本操作
package xss.netty.basicio; 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.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.Iterator; /** * NIO 基本知識點 */ public class NIOMainServerTest { //通道的管理,監聽客戶傳送的事件 private Selector selector; public static void main(String[] args) throws Exception{ NIOMainServerTest serverTest=new NIOMainServerTest(); serverTest.initServer(9999); serverTest.listen(); System.out.println("main executed."); } /** * 初始化ServerSocket 通道 * @param port * @throws IOException */ public void initServer(int port) throws IOException{ ServerSocketChannel serverSocketChannel=ServerSocketChannel.open(); //設定為非阻塞通道 serverSocketChannel.configureBlocking(false); //繫結埠 serverSocketChannel.socket().bind(new InetSocketAddress(port)); // this.selector=Selector.open(); //將selector 與 通道進行繫結,並且註冊ACCEPT事件 //selector會阻塞監聽是否有ACCEPT事件的到達。Selector.select() serverSocketChannel.register(this.selector, SelectionKey.OP_ACCEPT); System.out.println("Server init finished with prot="+port); } /** * 輪詢監聽selector上是否有需要處理的事件 * @throws IOException */ public void listen() throws IOException{ System.out.println("start listen..."); while (true){ //當註冊的事件到達時,方法返回;否則,該方法會一直阻塞 selector.select(); //獲得selector中選中的項的迭代器,選中的項為註冊的事件 Iterator iterator=this.selector.selectedKeys().iterator(); while(iterator.hasNext()){ SelectionKey selectionKey=(SelectionKey)iterator.next(); iterator.remove();//刪除已選的key,以防重複處理 //處理請求 this.handler(selectionKey); } } } /** * 事件型別請求的處理 * @param key * @throws IOException */ public void handler(SelectionKey key) throws IOException{ if(key.isAcceptable()){ //客戶端的連線請求事件 handlerAccept(key); }else if(key.isReadable()){ //處理客戶端傳送的資料 handelerRead(key); } } public void handlerAccept(SelectionKey key) throws IOException { ServerSocketChannel serverSocketChannel=(ServerSocketChannel) key.channel(); //建立與客戶端連線的通道 SocketChannel channel=serverSocketChannel.accept(); channel.configureBlocking(false); //給selector 繫結客戶端,並且監聽客戶端傳送的請求。即對於服務端來說是可讀取到客戶端的資料 //請求 channel.register(this.selector,SelectionKey.OP_READ); System.out.println("New Client connected"); } public void handelerRead(SelectionKey key) throws IOException { SocketChannel channel=(SocketChannel)key.channel(); //緩衝區的大小以實際情況來調整 ByteBuffer byteBuffer= ByteBuffer.allocate(1024); //讀取資料, -- 示例客戶端最大一次性發送1024 int read=channel.read(byteBuffer); if(read>0){ String readMsg=new String(byteBuffer.array()); System.out.println("Read message:"+readMsg); //響應客戶端 ByteBuffer outBuffer=ByteBuffer.wrap((readMsg+" is Ok").getBytes()); channel.write(outBuffer); }else{ System.out.println("client closed."); key.cancel(); } } }
作業系統IO Selector 模型類似