Netty(三)Discard Server 与 Handler

本文介绍了Netty中的Handler机制,包括其重要性和使用场景,并详细解释了如何自定义ServerHandler和ClientHandler来处理通讯过程中的消息收发。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Handler在netty中,占据非常重要地位,与Servlet中的Filter很想,通过Handler可以完成通讯报文的解码和编码、拦截指定的报文、统一对日志错误进行处理、统一对请求进行计数、控制Handler执行与否。

Handler注册要注意先后顺序:

Handler按照输入输出区分,分为ChannelInboundHandler和ChannelOutboundHandler两类。ChannelInboundHandler对输入数据进行按照注册的先后顺序处理;而ChannelOutboundHandler对输出数据进行按照注册的先后顺序的逆序处理,如下图所示:


自定义Handler:

其中ServerHandler比ClientHandler简单,只需要负责接收消息、显示和返回应答就好了,代码如下所示:

Server端:

public class DiscardServerHandler extends SimpleChannelInboundHandler<String> {

	@Override
	protected void channelRead0(ChannelHandlerContext ctx, String msg)
			throws Exception {
		// 收到客户端的消息
		String toConsole = ctx.channel().remoteAddress() + " said: " + msg;
		System.out.println(toConsole);
		// 分发消息给客户端
		ctx.writeAndFlush(msg + " received!\r\n");
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		cause.printStackTrace();
		ctx.close();
	}
	
	/**
	 * 本方法channelActive在channel被accept时候(即连接建立的时候被触发)
	 * @throws Exception 
	 */
	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		String toConsole = ctx.channel().remoteAddress() + " active!";
		System.out.println(toConsole);
		ctx.writeAndFlush("Welcome to " + InetAddress.getLocalHost().getHostName() + " service!\r\n");
		super.channelActive(ctx);
	}
}

上面的类继承了

Class SimpleChannelInboundHandler<T>

其中T是泛型表达形式,在这里最简单的系统上我们设置为String,当然也可以设置为其他自定义的类,这会在后续博客中详细说明

需要覆盖的最基本的方法:

1)channelRead0:当服务器接收到channel发送来的消息的处理方法

2)channelActive():当服务器accept客户端的连接请求后触发的方法

3)其他:包括一些异常处理等


Client端:

public class DiscardClientHandler extends SimpleChannelInboundHandler<String> {

	// 用于保存消息
//	private ByteBuf content;
	private String content;
	// 用于回调的handler
	private ChannelHandlerContext ctx;
	// 监听器
	private final ChannelFutureListener trafficGenerator = new ChannelFutureListener() {
		/*
		 * 监听函数,用于在异步返回channelfuture的时候启动
		 */
		@Override
		public void operationComplete(ChannelFuture future) throws Exception {
			if (future.isSuccess()) {
				System.out.println("Client is in listening!");
				generateTraffic();
			} else {
				future.cause().printStackTrace();
				future.channel().close();
			}
		}
	};
	
	@Override
	protected void channelRead0(ChannelHandlerContext ctx, String msg)
			throws Exception {
		String toConsole = "Server say: " + msg;
		System.out.println(toConsole);
		// Initialize and send the initial message
		generateTraffic();
	}
	
	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		String toConsole = "Client active!";
		System.out.println(toConsole);
		this.ctx = ctx;
		super.channelActive(ctx);
	}

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		String toConsole = "Client closed!";
		System.out.println(toConsole);
		super.channelInactive(ctx);
	}
	
	private void generateTraffic() throws IOException {
		// Flush the outbound buffer to the socket
		// Once flushed, generate the same amount of traffic again
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		content = br.readLine();
//		ctx.writeAndFlush(content + "\r\n").addListener(trafficGenerator);
		ctx.writeAndFlush(content + "\r\n");
	}
	
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
		// Close the connection when an exception is raised
		cause.printStackTrace();
		ctx.close();
	}
}

需要覆盖的最基本的方法:

1)channelRead0:当客户端接收到Server发送来的消息的处理方法,这里需要注意到的是,如果

2)channelActive():当服务器accept客户端的连接请求后触发的方法

3)channelInActive():当服务器断开与客户端的连接以后触发的方法

3)其他:包括一些异常处理等

自定义方法:

1)generateTraffic()

      这个方法可以放在channelActive(若放在这里,需要添加Listener,因为Active方法只执行一次)或者channelRead0(若放在这里,必须不能添加Listener,不然Read方法将只能执行一次)

自定义类对象:

1)ChannelFutureListener

     这个类用只有一个方法:当ChannelFuture的操作完成以后,需要做什么工作,是一个监听类,详细说明在后续的博客中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值