常见IO模型(BIO、NIO、AIO)

点点圈 提交于 2020-02-05 00:59:00

1.网络模型

  • a.编程模型 TCP UDP
    • TCP->可靠连接、使命必达、速度慢
    • UDP->不可靠、速度快

1.常见的IO模型

  • blocking IO == Old IO(BIO)

案例:如果不开线程,那么就会阻塞。

public class Server {
    public static void main(String[] args) throws Exception {
        ServerSocket ss = new ServerSocket();
        ss.bind(new InetSocketAddress("localhost", 8888));
        new Thread(()->{
            try {
                Socket s = ss.accept();
                BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
                System.out.println(br.readLine());
                br.close();
                s.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
        ss.close();
    }
}
  • Non-Blocking IO(NIO)->Java的API还不如C

调用Linux底层的epoll(),使用一个Channel,用Selector进行接受

ServerSocket是阻塞式的、Channel是双向的。

模型1

public class Server {
    public static void main(String[] args) throws Exception {
        ServerSocketChannel ssc = ServerSocketChannel.open();
        ssc.socket().bind(new InetSocketAddress("localhost", 8888));
        ssc.configureBlocking(false);

        System.out.println("server started, listening on: " + ssc.getLocalAddress());
        Selector selector = Selector.open();// selector是个大管家,进行调用epoll
        ssc.register(selector, SelectionKey.OP_ACCEPT);// 监听在OP_ACCEPT(连接操作)操作下进行处理

        while (true) {
            selector.select();// 轮训,无事件发生就进行等待
            Set<SelectionKey> keys = selector.selectedKeys();
            Iterator<SelectionKey> it = keys.iterator();
            while (it.hasNext()) {
                SelectionKey key = it.next();
                it.remove();
                handle(key);
            }
        }
    }

    private static void handle(SelectionKey key) {
        if(key.isAcceptable()) {// 写
            try {
                ServerSocketChannel ssc = (ServerSocketChannel) key.channel();// 新的通道
                SocketChannel sc = ssc.accept();
                sc.configureBlocking(false);
                sc.register(key.selector(), SelectionKey.OP_READ);// 设置为读
            } catch (IOException e) {
                e.printStackTrace();
            }
        }else if (key.isReadable()) {// 读
            SocketChannel sc = null;
            try{
                sc = (SocketChannel) key.channel();
                ByteBuffer buffer = ByteBuffer.allocate(512);
                buffer.clear();
                int len = sc.read(buffer);
                if(len != -1) {
                    System.out.println(new String(buffer.array(), 0, len));
                }
                ByteBuffer bufferToWrite = ByteBuffer.wrap("HelloClient".getBytes());
                sc.write(bufferToWrite);
            }catch (IOException e) {
                e.printStackTrace();
            }finally {
                if(sc != null) {
                    try {
                        sc.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

模型2

这个模型实现起来很难。

重要注意:

1.JDK中ByteBuff中,读写都是一个指针,如果读写操作,必须将其归位。

Netty用ByteBuf中,读写是2个指针。

2.Netty除了ByteBuf,还有ZeroCopy,Netty可以直接操作内存,跨过JVM。

  • AIO(Asynchronous IO)

是异步非阻塞型

异步:注册了事件,不去处理,让别人处理

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!