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中,后来又被自动删除了。

相关推荐
Java小白笔记36 分钟前
Java 单元测试怎么写:JUnit 5、Mockito 与 Spring Boot 方法级实战
java·junit·单元测试
CoderYanger1 小时前
前端基础——JavaScript(WebAPI)(下篇)
java·开发语言·前端·javascript·程序人生·面试·职场和发展
lisin-lee-cooper1 小时前
简单聊聊 Spring 框架源码
java·后端·spring
一木 之林1 小时前
七、一-AI 工程实践、插件化调试与软件交付
java·linux·c++
边境悍匪1 小时前
蜗牛学苑 Java 智能体学习 Day38|Spring AI Alibaba2 思维导图复盘
java·学习·spring
Co_Hui2 小时前
Java 静态内部类、非静态内部类、匿名内部类的区别?
java
Wang's Blog2 小时前
Java框架快速入门: Spring Security+OAuth2之自定义认证过滤器实现JSON登录
java·spring·json
Wang's Blog3 小时前
Java框架快速入门: Spring Security+OAuth2之密码验证规则与自定义注解
java·数据库·spring
一嘴一个橘子3 小时前
java - redis 缓存击穿 - 互斥锁
java
shehuiyuelaiyuehao3 小时前
算法39,位运算,消失的两个数字
java·数据结构·算法