BIO(Blocking I/O)

  1. 同步阻塞,数据的读取写入必须阻塞在一个线程内等待其完成

  2. IO 面向流(Stream oriented),流操作通常是阻塞的,而且是顺序的

  3. 在服务器端会有一个Acceptor线程监听客户端的连接,比如while(true) { accept(); }

  4. 当只有一个线程的时候,服务器一旦接收到一个连接请求,就会建立通信套接字,然后在这个通信套接字上进行读写操作,此时不能再接收其他客户端连接请求,只能等待当前连接的客户端的操作执行完成

  5. socket.accept()、 socket.read()、 socket.write() 涉及的三个主要函数都是同步阻塞的

  6. 可以使用多线程操作,每个请求用一个线程处理,并通过线程池机制改善线程的创建和回收成本

  7. 同步阻塞:调用者发起一个操作后,等待操作完成,然后在执行下面的操作

  8. 同步非阻塞:调用者发起一个操作后,不会等待操作完成,而是继续执行后续代码,但程序会定期检查操作的状态(轮询),如果操作尚未完成,程序可以决定再次检查或执行其他任务

NIO(Non Blocking IO)

  1. 同步非阻塞,服务器实现模式为一个线程可以处理多个请求(连接),客户端发送的连接请求都会注册到 多路复用器 selector 上,多路复用器轮询到连接有 IO 请求就进行处理

  2. nio支持面向缓冲的,基于通道的I/O操作方法,提供了SocketChannel 和 ServerSocketChannel两种不同的套接字通道实现,两种通道都支持阻塞和非阻塞两种模式

  3. NIO 面向缓冲区(Buffer oriented),这意味着在使用 NIO 时,用户不是直接从流中读取数据或写入数据到流中,而是先将数据读入缓冲区,处理完毕后再从缓冲区写出

  4. 首先,需要将一个或多个 SelectableChannel 注册到 Selector 对象上,注册时要标明操作类型,之后通过调用 Selectorselect() 方法,可以检查所有注册的通道是否有任何符合注册条件的就绪事件

    Untitled

  5. 当客户端的数据尚未发送到服务器中时,如果服务器尝试从套接字读取数据,套接字的缓冲区内无数据(此时就是数据未准备好),之前的bio会阻塞并等待数据的到达,现在的nio会先尝试读,如果尝试失败,则立即返回,之后服务器可以通过轮询的方式检查数据何时准备好,或者设置异步操作,在数据到达时触发回调