04-NIO Channel

NIO Channel

  • Channel (java.nio.channels.Channel) 是 NIO 的三个核心组件之一,Channel 在NIO中代表通道,在JDK中是一个接口。

一、Channel和流

  • Channel 可以是双向的,既可以通过Channel读数据,也可以写数据,流的话要么是输入流,要么是输出流
  • 不能直接通过 Channel 读写数据,必须通过buffer操作,程序通过Buffer间接的和Channel打交道,程序永远不能绕过buffer直接操作Channel,而流是可以直接读写的
  • Channel的读写可以是非阻塞的,而流是阻塞的

二、Channel的主要实现类

实现类作用场景
SocketChannel客户端用来发起 TCP连接的 的 Channel
ServerSocketChannel服务端用于监听客户端TCP连接的Channel,每接受到一个连接,则会创建一个SocketChannel
DatagramChannel通过 UDP 读写数据的 Channel
FileChannel从文件读写数据的 Channel

在 Netty 中主要涉及到的是 SocketChannel 和 ServerSocketChannel ,下面给出这两个的继承图,比较类似:

在这里插入图片描述

在这里插入图片描述

三、从Socket到Channel

  • 最初的网络编程最熟悉的类是 Socket 和 ServerSocket,那么 Socket 和 ServerSocket VS SocketChannel 和 ServerSocketChannel ,这两组类之间的区别和联系是什么?

3.1 Socket和ServerSocket

  • Socket 和 ServerSocke 是对应的,分别对应客户端和服务端,它们是 java.net 下面实现 Socket 通信的类,只支持阻塞通信(或者自己实现非阻塞通信),通常在 ServerSocket 实现的服务端是为每一个客户端分配一个线程(或者线程池),由此能够支持的客户端数量有限。
  • 在阻塞IO的通信中我们就是使用这两个类,在文章: 03-BIO、NIO到Netty 的BIO示例中有给出,核心伪代码如下:
客户端:
{
    Socket socket = new Socket(IP, PORT);

    //后续数据读写:
    socket.getOutputStream()
    socket.getInputStream()    
}


服务端:
{
    ServerSocket serverSocket = new ServerSocket(PORT);
    while (true) {
        Socket socket = serverSocket.accept();

        //线程池处理连接
        threadPool.execute(new ServerHandler(socket));
    }    
}
  • Socket:可以理解为客户端与服务端的一个连接,比如客户端 Socket socket=new Socket(ip,port);其中 socket 这个 Socket 对象就代表客户端和对应ip端口的一个连接;
  • ServerSocket:可以理解为服务端等待客户端连接的一个Socket对象,比如服务端 ServerSocket serverSocket = new ServerSocket(port);其中 serverSocket 代表服务端监听在 port 的一个 Socket,这里并不代表一个连接,仅仅代表一个服务的监听,ServerSocket收到连接请求之后通过 accept方法可以打开一个Socket对象,与客户端进行通信。

3.2 SocketChannel和ServerSocketChannel

  • SocketChannel 和 ServerSocketChannel 是对应的,分别对应客户端和服务端,他们是 java.nio 下面实现通信的类,支持异步通信(通过参数配置)
  • 在NIO的通信中我们就是使用这两个类,在文章: 03-BIO、NIO到Netty 的NIO示例中有给出,核心伪代码如下:
{
     Selector selector = Selector.open();
     ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
     serverSocketChannel.configureBlocking(false);
     serverSocketChannel.socket().bind(new InetSocketAddress(port));
     serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
     
     while(true){
          selector.select();
          Set<SelectionKey> selectionKeys = selector.selectedKeys();
          //处理事件      
    }
}
  • SocketChannel:可以理解为客户端与服务端的一个Tcp Channel通道,类比于Socket
  • ServerSocketChannel:可以绑定端口等待监听,类比于 ServerSocket,ServerSocketChannel的accept方法会返回一个 SockerChannel
  • SocketChannel和ServerSocketChannel的使用需要结合 Selector 组件,通过Selector 实现少量线程管理大量连接。

3.3 联系

  • 下面图是这四个类大致的关系,我们看到从功能上来看 Socket 和 SocketChannel很类似,SocketChannel 和 ServerSocketChannel很类似,但是Channel提供了非阻塞的通信模式,因此可以简单地认为Channel是对Socket的升级。而且通过getChannel()方法和socket()方法,他们之间可以相互转换。

在这里插入图片描述

  • 通信时,服务器必须先建立 ServerSocket 或者 ServerSocketChannel 监听并等待客户端的连接,客户端必须建立相对应的 Socket 或者 SocketChannel 来与服务器建立连接,服务器在接受到客户端的连接受,会生成一个 Socket 或者 SocketChannel 与此客户端通信,注意重新生成的连接所使用的端口与监听的端口是不一样的。

四、Netty Channel

  • 前面描述的是 java.nio.channels.Channel,是JDK NIO 中的 Channel,和 Netty中的Channel还不一样,Netty中自己定义了 io.netty.channel.Channel,Netty的Channel 后续专门再分析,这里只提一下,在Netty中 io.netty.channel.Channel 接口的实现类 有些封装了 JDK的Channel,比如在 NioServerSocketChannel 中就封装了 NIO 中的ServerSocketChannel,SocketChannel和SelectionKey等组件,因此可以认为Netty重新定义了一套Channel接口以及相关的继承体系可以更好的组织类之间的关系,提供统一的API,但是其底层最终还是会用到JDK NIO的相关实现,最底层的通信类还是用的JDK的。

参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值