NIO之重要概念

Channel

通道,建立在应用程序和操作系统之间的交换事件,传递内容的渠道。一个通道具有一个专属的文件状态描述符。应用程序可以通过通道读取和向操作系统写入数据。

  • 所有被Selector选择器注册的通道,只能是继承了SelectableChannel类的子类。
  • ServerSocketChannel:应用服务器的监听通道。只有通过这个通道,应用程序才能向操作系统注册支持"多路复用IO"的兼容通道,同时支持TCP和UDP协议。
  • ScoketChannel:TCP Socket套接字的监听通道,一个Socket套接字对应了一个客户端IP:端口 到 服务器IP:端口的通信连接。
  • DatagramChannel:UDP 数据报文的监听通道。

Buffer

  • Java NIO框架为每一种需要支持数据读写的通道继承了Buffer的支持。
  • ServerSocketChannel通道只支持OP_ACCEPT事件的监听,它不能只能进行网络数据内容的读写。所有它是没有Buffer集成的。
  • Buffer有两种工作模式:读模式和写模式。读模式只能从Buffer中读取数据,不能进行写操作。写模式下,可以写和读操作,所有可能会出现脏读的情况。所以一旦准备从Buffer中读数据,一定要将Buffer的状态设为读模式。 Buffer的读/写模式
  • position:缓存区目前操作的位置
  • limit:缓存区最大可以进行操作的位置。缓存区的读模式由这个limit属性控制。
  • capatity:缓存区的最大容量 。是在缓存区创建的时候指定的,不可改变。由于高并发是通道数量会很庞大,所有每一个缓存区的容量最好不要过大。

Selector

选择器。根据Selector的岗位职责,我们可以把它称之为“轮询代理器”,""事件订阅器,"Channel容器管理机"等。

  • 事件订阅和Channel管理
    应用程序向Selector注册它需要关注的Channel,以及Channel会对哪些IO事件感兴趣。Selector中会维护一个已经注册的Channel的容器。
  • 轮询代理
    应用层不再通过阻塞模式或非阻塞模式直接询问操作系统事件有没有发生,而是由Selector代其询问。
  • 实现不同操作系统的支持
  • 多列复用IO技术是需要操作系统支持的。其特点是操作系统可以同时扫描在同一个端口上不同网络连接的时间。JVM必须为不同的操作系统的多路复用IO实现编写不同的代码。

JAVA NIO 框架简要设计分析

Java NIO对多路复用IO的支持,主要的基础是java.nio.channels.spi.SelectorProvider抽象类,其中的几个主要抽象方法包括:

  • public abstract DatagramChannel openDatagramChannel():创建和这个操作系统匹配的UDP 通道实现。
  • public abstract AbstractSelector openSelector():创建和这个操作系统匹配的NIO选择器,就像上文所述,不同的操作系统,不同的版本所默认支持的NIO模型是不一样的。
  • public abstract ServerSocketChannel openServerSocketChannel():创建和这个NIO模型匹配的服务器端通道。
  • public abstract SocketChannel openSocketChannel():创建和这个NIO模型匹配的TCP Socket套接字通道(用来反映客户端的TCP连接)。
    NIO实现
    很明显,不同的SelectorProvider实现对应了不同的 选择器。由具体的SelectorProvider实现进行创建。另外说明一下,实际上netty底层也是通过这个设计获得具体使用的NIO模型,以下代码是Netty 4.0中NioServerSocketChannel进行实例化时的核心代码片段:
private static ServerSocketChannel newSocket (SelectorProvider provider){
	try {
	    /**
	     *  Use the {@link SelectorProvider} to open {@link SocketChannel} and so remove condition in
	     *  {@link SelectorProvider#provider()} which is called by each ServerSocketChannel.open() otherwise.
	     *
	     *  See <a href="See https://github.com/netty/netty/issues/2308">#2308</a>.
	     */
	    return provider.openServerSocketChannel();
	} catch (IOException e) {
	    throw new ChannelException(
	            "Failed to open a server socket.", e);
	}
}

猜你喜欢

转载自blog.csdn.net/java852987/article/details/82885791
今日推荐