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) ; } }