Netty:ChannelInitializer添加到ChannelPipeline完成任务以后会自动删除自己

说明

io.netty.channel.ChannelInitializer是一个特殊的ChannelInboundHandler。它的主要作用是向 Channel对应的ChannelPipeline中增加ChannelHandler。执行完ChannelInitializer的initChannel(C ch)函数以后,ChannelInitializer就会从ChannelPipeline自动删除自己,防止重复进入。

一般是通过Bootstrap.handler(ChannelHandler) 、ServerBootstrap.childHandler(ChannelHandler)的方式分别在客户端、服务端中将ChannelInitializer这个ChannelHandler增加到ChannelPipeline中。

示例

思路

我们来验证下ChannelInitializer是否会被自动删除。我们在ChannelInitializer的initChannel(C ch)函数末尾打印出来当前ChannelPipeline中已经添加的ChannelHandler名称;在Channel连接成功以后,再打印出来当前ChannelPipeline中已经添加的ChannelHandler名称,两者对照下,就能看出来是否被自动删除了。

代码片段

复制代码
package com.thb.power.terminal;

import java.io.BufferedReader;
import java.io.InputStreamReader;

import com.thb.power.packet.register.RegisterRequestPacket;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;

/**
 * 主函数
 * @author thb
 *
 */
public class Terminal {
	// 要连接的服务端的host 
	static final String HOST = System.getProperty("host", "127.0.0.1"); 
	// 要连接的服务端的端口号 
	static final int PORT = Integer.parseInt(System.getProperty("port", "22335"));

	public static void main(String[] args) throws Exception {
		// 配置客户端
		EventLoopGroup group = new NioEventLoopGroup();
		try {
			Bootstrap b = new Bootstrap();
			b.group(group)
			 .channel(NioSocketChannel.class)
			 .option(ChannelOption.TCP_NODELAY, true)
			 .handler(new TerminalInitializer());
			
			// 启动客户端
			Channel ch = b.connect(HOST, PORT).sync().channel();		
			
			// 查看ChannelPipeline添加的ChannelHandler名称
			System.out.println("after channel connected:");
			for (String name : ch.pipeline().names()) {
				System.out.println("handler name: " + name);
			} 
			
			ChannelFuture lastWriteFuture = null;
			BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
			System.out.println("please input(register):");
			for (;;) {
				String line = in.readLine();
				if (line == null) {
					break;
				}				

				// 如果用户输入register,表示命令客户端发送注册请求给服务器
				if (line.toLowerCase().equals("register")) {
					RegisterRequestPacket registerRequest = new RegisterRequestPacket();
					// 返回的ByteBuf存放着注册请求的数据
					ByteBuf buf = registerRequest.build(ch);
					
					lastWriteFuture = ch.writeAndFlush(buf);						
				}
			}
			
			if (lastWriteFuture != null) {
				lastWriteFuture.sync();
			}
		} finally {
			// 关闭event loop以便终止所有的线程
			group.shutdownGracefully();
		}

	}

}


// ChannelInitializer的子类
package com.thb.power.terminal;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

public class TerminalInitializer extends ChannelInitializer<SocketChannel> {

	 @Override
	 public void initChannel(SocketChannel ch) throws Exception {
		 ChannelPipeline p = ch.pipeline();
		 p.addLast(new LoggingHandler(LogLevel.INFO));
		 
		 // 查看ChannelPipeline添加的ChannelHandler名称
		 System.out.println("in initChannel(SocketChannel ch) method of TerminalInitializer:");
		 for (String name : ch.pipeline().names()) {
			 System.out.println("handler name: " + name);
		 } 
	 }
}

运行输出

从上面输出可以看出,ChannelInitializer开始被添加到ChannelPipeline中,后来又被自动删除了。

相关推荐
缓慢更新2 小时前
审批的加签与会签:多人意见怎么合
android·java·数据库·低代码·rxjava
yuniko-n3 小时前
【JUC】volatile 非原子性深入解析
java
sun_weitao3 小时前
极简版 MCP 工具实现方案
java·linux·服务器
金銀銅鐵5 小时前
[Java] 展示增删元素时 LinkedList 的内部变化
java·后端·ai编程
布吉岛的石头5 小时前
Java 程序员第 50 阶段3:数据工程:预训练语料清洗与去重
java·开发语言·人工智能·深度学习·transformer
大文说跨境5 小时前
防关联浏览器的指纹覆盖到什么程度:六类参数的实测与自检方法
java·指纹浏览器·tiktok运营
Carol06306 小时前
上肢及肩肘关节
java·服务器·数据库
yliucherish6 小时前
Log4Shell 复现实录:我读 OpenJDK 源码,发现两道防线的默认值竟然相反
java
维拉德6 小时前
Java新人第一次接打标需求:从抓包找接口到客户端展示
java
luobobo8966 小时前
支付回调验签连续失败三天,最后发现是网关的时间戳单位问题
java