在 Netty 中,什么是 Channel ? 什么是 ChannelHandlerContext?

Sherwin.Wei Lv7

在 Netty 中,什么是 Channel ? 什么是 ChannelHandlerContext?

回答重点

在 Netty 中,Channel 表示一个网络连接,抽象了底层的网络操作,提供绑定、连接、读写和关闭等操作,是网络 I/O 操作的核心抽象。

ChannelHandlerContext 是 Netty 中用来在 ChannelPipeline 中传递数据和处理事件的上下文对象,它连接 ChannelHandler 和 ChannelPipeline,用于在 ChannelPipeline 中传递事件和操作。

扩展知识

ChannelHandlerContext 介绍

  1. ChannelHandlerContext 可以通过 ctx.channel() 获得当前的 Channel,通过 ctx.pipeline() 获得当前的 ChannelPipeline,允许你访问管道中的其他 ChannelHandler。
  2. ChannelHandlerContext 可以用于传递消息或者事件。在 Netty 中,当数据流经 ChannelPipeline 时,ChannelHandler 会调用 ChannelHandlerContext 的方法来触发事件或者向下游传递数据。
  3. 通过调用 ctx.fireChannelRead()、ctx.fireChannelReadComplete() 等方法,ChannelHandlerContext 可以将事件和消息传递给 ChannelPipeline 中的下一个 ChannelHandler。
  4. ChannelHandlerContext 提供了许多操作方法,如 writeAndFlush() 来向下游发送数据,close() 来关闭连接等。

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class MyChannelInboundHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// 处理接收到的消息
System.out.println("Received message: " + msg);

// 将消息传递给下一个 handler
ctx.fireChannelRead(msg);
}

@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// 连接建立时的处理逻辑
System.out.println("Channel is active.");
super.channelActive(ctx);
}
}

什么是 Channel

翻译过来就是通道。

我们可以往通道里写数据,也可以从通道里读数据,它是双向的,而与之配套的是 Buffer,也就是你想要往一个通道里写数据,必须要将数据写到一个 Buffer 中,然后写到通道里。

从通道里读数据,必须将通道的数据先读取到一个 Buffer 中,然后再操作。

在 NIO 中 Channel 有多种类型:

  • SocketChannel
  • ServerSocketChannel
  • DatagramChannel
  • FileChannel

SocketChannel

对标 Socket,我们可以直接将它当做所建立的连接

通过 SocketChannel ,我们可以利用 TCP 协议进行读写网络数据。

ServerSocketChannel

可以对标 ServerSocket,也就是服务端创建的 Socket。

它的作用就是监听新建连的 TCP 连接,为新进一个连接创建对应的 SocketChannel。

之后,通过新建的 SocketChannel 就可以进行网络数据的读写,与对端交互。

可以看到它主要是用来接待新连接,这功能主要就是服务端做的,所以叫 ServerSocketChannel。

DatagramChannel

看到 Datagram 应该就知道是 UDP 协议了,是无连接协议。

利用 DatagramChannel 可以直接通过 UDP 进行网络数据的读写。

FileChannel

文件通道,用来进行文件的数据读写。

我们日常开发主要是基于 TCP 协议,所以我们把精力放在 SocketChannel 和 ServerSocketChannel 上即可。

我们再回过头来继续看看 SocketChannel 和 ServerSocketChannel。

SocketChannel 主要在两个地方出现:

  1. 客户端,客户端创建一个 SocketChannel 用于连接至远程的服务端。
  2. 服务端,服务端利用 ServerSocketChannel 接收新连接之后,为其创建一个 SocketChannel 。

随后,客户端和服务端就可以通过这两个 SocketChannel 相互发送和接收数据。

ServerSocketChannel 主要出现在一个地方:服务端。

服务端需要绑定一个端口,然后监听新连接的到来,这个活儿就由 ServerSocketChannel 来干。

服务端内常常会利用一个线程,一个死循环,不断地接收新连接的到来。

1
2
3
4
5
6
7
8
9
ServerSocketChannel serverSocketChannel 
= ServerSocketChannel.open();
......
while(true){
// 接收的新连接
SocketChannel socketChannel =
serverSocketChannel.accept();
.......
}

至此,想必你应该清楚 ServerSocketChannel 和 SocketChannel 的区别和作用了。

Comments