NIO相关概念介绍:缓冲区Buffer,通道Channel,多路复用器Selector

本篇博文参考书籍《Netty权威指南》。

1、缓冲区Buffer

Buffer是一个对象。它包含一些要写入或者读出的数据。在面向流的I/O中,可以将数据写入或者将数据直接读到Stream对象中。在NIO中,所有的数据都是用缓冲区处理。这也就是很多博客说,IO是面向流的,NIO是面向缓冲区的。缓冲区实质是一个数组,通常它是一个字节数组(ByteBuffer),也可以使用其他类的数组。但是一个缓冲区不仅仅是一个数组,缓冲区提供了对数据的结构化访问以及维护读写位置(limit)等信息。
最常用的缓冲区是ByteBuffer,一个ByteBuffer提供了一组功能于操作byte数组。除了ByteBuffer,还有其他的一些缓冲区,事实上,每一种Java基本类型(除了Boolean)都对应一种缓冲区,具体如下:

  • ByteBuffer:字节缓冲区
  • CharBuffer:字符缓冲区
  • ShortBuffer:短整型缓冲区
  • IntBuffer:整型缓冲区
  • LongBuffer:长整型缓冲区
  • FloatBuffer:浮点型缓冲区
  • DoubleBuffer:双精度浮点型缓冲区
    这里写图片描述

2、通道Channel
channel是一个通道,可以通过它读取和写入数据,他就像自来水管一样,网络数据通过Channel读取和写入。通道和流不同之处在于通道是双向的,流只是在一个方向移动,而且通道可以用于读,写或者同时用于读写。因为Channel是全双工的,所以它比流更好地映射底层操作系统的API,特别是在UNIX网络编程中,底层操作系统的通道都是全双工的,同时支持读和写。
Channel有四种实现:

  • FileChannel
  • DatagramChannel
  • SocketChannel
  • ServerSocketChannel

FileChannel是从文件中读取数据。
DatagramChannel从UDP网络中读取或者写入数据。
SocketChannel从TCP网络中读取或者写入数据。
ServerSocketChannel允许你监听来自TCP的连接,就像服务器一样。每一个连接都会有一个SocketChannel产生。这句话的意思就是,ServerSocketChannel用于服务端,SocketChannel用于客户端。

3、多路复用器Selector Selector会不断轮询注册在上面的Channel,如果某个Channel上面有新的TCP连接接入,读和写事件,这个channel就处于就绪状态,会被Selector轮询出来,然后通过SelectionKey可以获取Channel的集合,进行后续的I/O操作。一个多路复用器Selector可以同时轮询多个Channel,由于JDK使用了epoll()代替传统的select实现,所以它没有最大连接句柄1024/2048的限制。这就意味着只需一个线程负责Selector的轮询,就可以接入成千上万的客户端。在前面的博文中我写了一个通过使用线程池来处理tcp连接的例子,那个例子中是一种伪阻塞的I/O .因为每来一个TCP连接,就要产生一个线程去处理。而selector只需要一个线程负责就可以处理多个连接请求。 本文完。