- 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>() {@Overrideprotected 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);}}