初学IO之AIO

一 前言

简介

AIO: 事件驱动I/O,也叫NIO 2.0引入了新的异步通道的概念,并提供了异步文件通道和异步套接字通道的实现。不需要过多的Selector对注册的通道进行轮询即可实现异步读写,从而简化了NIO的编程模型。

不多说,上代码,都有注释

二 Java代码

1.服务端

package dcocd.netty.tool.io.aio.server;

/**
 * AIO Server 启动
 *
 * @author guohongjun@dcocd.cn
 * @Date 2020/5/13 11:37
 */
public class AioServer {
   

    /**
     * 默认端口号
     */
    private static int DEFAULT_PORT = 12345;
    /**
     * AIO Server处理器
     */
    private static AioServerHandler aioServerHandler;
    /**
     * 客户端数量
     */
    public volatile static long clientCount = 0;

    public static void start() {
   
        start(DEFAULT_PORT);
    }

    public static synchronized void start(int port) {
   
        if (aioServerHandler != null) {
   
            return;
        }
        aioServerHandler = new AioServerHandler(port);
        new Thread(aioServerHandler, "aio-server-" + port).start();
    }

    public static void main(String[] args) {
   
        AioServer.start();
    }
}

2.服务端处理器

package dcocd.netty.tool.io.aio.server;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.util.concurrent.CountDownLatch;

/**
 * AIO Server处理器
 *
 * @author guohongjun@dcocd.cn
 * @Date 2020/5/13 14:18
 */
public class AioServerHandler implements Runnable {
   

    private static Logger logger = LoggerFactory.getLogger(AioServerHandler.class);

    /**
     * 作用:在完成一组正在执行的操作之前,允许当前的线程一直阻塞
     */
    protected CountDownLatch countDownLatch;
    /**
     * AIO Server 服务端通道
     */
    protected AsynchronousServerSocketChannel socketChannel;

    /**
     * 构造方法
     *
     * @param port 端口号
     */
    public AioServerHandler(int port) {
   
        try {
   
            // 创建服务通道
            socketChannel = AsynchronousServerSocketChannel.open();
            // 绑定端口
            socketChannel.bind(new InetSocketAddress(port));
            logger.info("aio-server start successful by port : " + port);
        } catch (IOException e) {
   
            logger.error("aio-server create error : " + e.getMessage());
        }
    }

    @Override
    public void run() {
   
        // CountDownLatch 初始化
        // 它的作用:在完成一组正在执行的操作之前,允许当前的线程一直阻塞;
        // 此处,让线程在此阻塞,防止服务端执行完成后退出,也可以使用while(true)+sleep
        // 生产环境就不需要担心这个问题,因为服务端是不会退出的
        countDownLatch = new CountDownLatch(1);
        // 用于接收客户端的链接
        socketChannel.accept(this, new AioServerAcceptHandler());
        try {
   
            // 使当前线程等待直到锁存器倒计时到零
            countDownLatch.await();
        } catch (InterruptedException e) {
   
            logger.error("AioServerHandler run() CountDownLatch await() error " + e.getMessage());
        }
    }
}

3.服务端链接处理器

package dcocd.netty.tool.io.aio.server;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;

/**
 * 作为 Aio Server handler 接收客户端连接
 *
 * @author guohongjun@dcocd.cn
 * @Date 2020/5/13 14:32
 */
public class AioServerAcceptHandler implements CompletionHandler<AsynchronousSocketChannel, AioServerHandler> {
   

    private static Logger logger = LoggerFactory.getLogger(AioServerAcceptHandler.class);

    /**
     * Invoked when an operation has completed.
     * 在操作完成时调用,即链接客户端成功后
     *
     * @param channel          I/O操作的结果 通道
     * @param aioServerHandler Aio Server 服务端处理器
     */
    @Override
    public void completed(AsynchronousSocketChannel channel, AioServerHandler aioServerHandler) {
   
        // 继续接收其他客户端的请求
        AioServer.clientCount++;
        logger.info("aio-client on line count : " + AioServer.clientCount);
        // 使 Aio Server 服务端处理器的服务端通道接受客户端连接
        aioServerHandler.socketChannel.accept(aioServerHandler, this);
        // 创建新的 Buffer,并开辟一个1M的缓冲区
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        // 异步读,第三个参数为接收消息回调的业务 handler
        channel.read(buffer, buffer, new AioServerReadHandler(channel));
    }

    /**
     * Invoked when an operation fails.
     * 操作失败时调用
     *
     * @param exc              指示I/O操作失败原因的异常
     * @param aioServerHandler Aio Server 服务端处理器
     */
    @Override
    public void failed(Throwable exc, AioServerHandler aioServerHandler) {
   
        logger.error("aio-server received aio-client connection error : " + exc.getMessage());
        // 减少闩锁的计数
        aioServerHandler.countDownLatch.countDown();
        logger
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值