NIO簡單介
NIO 非阻塞IO模型,基于緩沖區(Buffer)讀寫數據,讀寫后的數據通過通道(Channel)進行傳輸,采用選擇器(Selector)管理多個通道從而實現高并發。
核心組件:1. Buffer 為一個內存數組作為數據容器,代替傳統的InputStream和OutputStream;2. Channel 雙向數據傳輸;3. Selector 監聽多通道區別于傳統的單線程管理多連接傳統的IO模型
阻塞、非阻塞、多路復用、信號驅動、異步IO簡單的NIO服務器接收客戶端TCP請求
public void start ( int port) throws IOException { Selector selector = Selector . open ( ) ; createChannel ( selector, port) ; while ( true ) { selector. select ( ) ; Iterator < SelectionKey > keys = selector. selectedKeys ( ) . iterator ( ) ; while ( keys. hasNext ( ) ) { SelectionKey key = keys. next ( ) ; keys. remove ( ) ; if ( key. isAcceptable ( ) ) { ServerSocketChannel socketChannel = ( ServerSocketChannel ) key. channel ( ) ; SocketChannel channel = socketChannel. accept ( ) ; channel. configureBlocking ( false ) ; channel. register ( selector, SelectionKey . OP_READ) ; continue ; } if ( key. isReadable ( ) ) { SocketChannel channel = ( SocketChannel ) key. channel ( ) ; ByteBuffer buffer = ByteBuffer . allocate ( 1024 ) ; int bytes = channel. read ( buffer) ; if ( bytes == - 1 ) { channel. close ( ) ; continue ; } buffer. flip ( ) ; String message = new String ( buffer. array ( ) , 0 , bytes) ; System . out. println ( "接收到消息" ) ; channel. write ( ByteBuffer . wrap ( message. getBytes ( ) ) ) ; } } } }
private void createChannel ( Selector selector, int port) throws IOException { ServerSocketChannel socketChannel = ServerSocketChannel . open ( ) ; socketChannel. bind ( new InetSocketAddress ( port) ) ; socketChannel. configureBlocking ( false ) ; socketChannel. register ( selector, SelectionKey . OP_ACCEPT) ; }
Netty基于NIO的異步事件驅動的網絡應用框架
特性:異步和事件驅動、高性能(高效的線程模型和緩沖區機制)、易使用和靈活可擴展
涉及到 channel 、callback(事件發生時的回調)、Future和Promise(異步計算)、EventLoop(事件循環)、Pipeline和ChannelHandler管道和處理器、bootstrap引導類
public static void start ( int port) { EventLoopGroup bossGroup = new NioEventLoopGroup ( ) ; EventLoopGroup workerGroup = new NioEventLoopGroup ( ) ; try { start ( bossGroup, workerGroup, port) ; } catch ( Exception e) { log. warn ( "Netty服務【{}】發生異常" , port, e) ; } finally { bossGroup. shutdownGracefully ( ) ; workerGroup. shutdownGracefully ( ) ; } }
private static void start ( EventLoopGroup bossGroup, EventLoopGroup workerGroup, int port) throws InterruptedException { ServerBootstrap serverBootstrap = new ServerBootstrap ( ) ; serverBootstrap. group ( bossGroup, workerGroup) . channel ( NioServerSocketChannel . class ) . handler ( new LoggingHandler ( ) ) . childHandler ( new ChannelInitializer < SocketChannel > ( ) { @Override protected void initChannel ( SocketChannel socketChannel) { socketChannel. pipeline ( ) . addLast ( new IotDataDecoder ( ) , new IotBusinessDecoder ( ) ) ; } } ) ; ChannelFuture channelFuture = serverBootstrap. bind ( port) . sync ( ) ; channelFuture. channel ( ) . closeFuture ( ) . sync ( ) ; }
private void write ( InputStream stream, String targetPath) throws IOException { FileChannel outChannel = FileChannel . open ( Paths . get ( targetPath) , StandardOpenOption . CREATE, StandardOpenOption . WRITE) ; ReadableByteChannel inChannel = Channels . newChannel ( stream) ; ByteBuffer buffer = ByteBuffer . allocate ( 2048 ) ; while ( inChannel. read ( buffer) != - 1 ) { buffer. flip ( ) ; outChannel. write ( buffer) ; buffer. compact ( ) ; } buffer. flip ( ) ; while ( buffer. hasRemaining ( ) ) { outChannel. write ( buffer) ; } }