Netty之ChannelHandler初解
Netty
2023-09-27 14:28:03 时间
目录
ChannelHandlerContext和NioSocketChannel写入数据时有什么不同
Pipeline添加多个ChannelHandler有什么意义
目标
- 掌握ChannelHandler基本使用方法。
- 熟悉入栈ChannelHandler和出栈ChannelHandler的执行顺序。
- 分析ChannelHandlerContext和NioSocketChannel写入数据时有什么不同。
- 了解Pipeline添加多个ChannelHandler有什么意义。
Netty版本
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.87.Final</version>
</dependency>
Netty官方API
Netty API Reference (4.1.89.Final)https://netty.io/4.1/api/index.html
实战
Netty服务器
package com.ctx.netty;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.extern.slf4j.Slf4j;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
/**
* Netty服务器
*/
@Slf4j
public class HandlerTest {
public static void main(String[] args) {
new ServerBootstrap().group(new NioEventLoopGroup())
.channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel channel) throws Exception {
ChannelPipeline pipeline = channel.pipeline();
//new HandlerTest().inboundHandlerTest(channel, pipeline);
//new HandlerTest().outboundHandlerTest(channel, pipeline);
//new HandlerTest().diff(channel, pipeline);
new HandlerTest().packageTest(channel, pipeline);
}
}).bind(8999);
}
}
入栈ChannelHandler读入数据顺序案例
/**
* 入栈ChannelHandler,读入数据时,调用顺序:先加入的ChannelHandler先执行。
*/
public void inboundHandlerTest(NioSocketChannel channel, ChannelPipeline pipeline) {
pipeline.addLast("InboundHandler", new ChannelInboundHandlerAdapter() {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
log.info("InboundHandler读入数据");
ctx.fireChannelRead(msg);
}
});
pipeline.addLast("InboundHandler2", new ChannelInboundHandlerAdapter() {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
log.info("InboundHandler2读入数据");
ctx.fireChannelRead(msg);
}
});
}
出栈ChannelHandler写出数据顺序案例
/**
* 出栈Handler,写出数据时,调用顺序:先加入的Handler后执行。
*/
public void outboundHandlerTest(NioSocketChannel channel, ChannelPipeline pipeline) {
pipeline.addLast("OutboundHandler", new ChannelOutboundHandlerAdapter() {
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
log.info("OutboundHandler写出数据");
ctx.write(msg, promise);
}
});
pipeline.addLast("OutboundHandler2", new ChannelOutboundHandlerAdapter() {
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
log.info("OutboundHandler2写出数据");
ctx.write(msg, promise);
}
});
}
ChannelHandlerContext和NioSocketChannel写入数据时有什么不同
/**
* ChannelHandlerContext和NioSocketChannel写入数据时有什么不同?
* ChannelHandlerContext写入数据以后,调用顺序:从当前这个Handler(有写入操作的Handler)往前出栈的Handler。
* NioSocketChannel写入数据以后,调用顺序:从Pipeline的头部往后寻找出栈的Handler。
*/
public void diff(NioSocketChannel channel, ChannelPipeline pipeline){
pipeline.addLast("OutboundHandler", new ChannelOutboundHandlerAdapter() {
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
log.info("OutboundHandler写出数据");
ctx.write(msg, promise);
}
});
pipeline.addLast("InboundHandler", new ChannelInboundHandlerAdapter() {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
log.info("InboundHandler读入数据");
ctx.writeAndFlush(channel.alloc().buffer().writeBytes("Hello World!".getBytes()));
//channel.writeAndFlush(channel.alloc().buffer().writeBytes("Hello World!".getBytes()));
ctx.fireChannelRead(msg);
}
});
pipeline.addLast("OutboundHandler2", new ChannelOutboundHandlerAdapter() {
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
log.info("OutboundHandler2写出数据");
ctx.write(msg, promise);
}
});
}
Pipeline添加多个ChannelHandler有什么意义
/**
* Pipeline添加多个Handler有什么意义?
* 相当于给流水线添加了多个工序,每个工序职责不同。在不同的Handler中写不同的业务,各个出栈入栈的Handler之间还可以通过:
* ctx.write(msg, promise)或ctx.fireChannelRead(msg)传递封装的数据。
*
*/
public void packageTest(NioSocketChannel channel, ChannelPipeline pipeline){
pipeline.addLast("InboundHandler", new ChannelInboundHandlerAdapter() {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
log.info("InboundHandler读入数据");
ByteBuf by = (ByteBuf) msg;
String name = by.toString(Charset.forName("UTF-8"));
Map<String, Object> map = new HashMap<>();
map.put("name",name);
ctx.fireChannelRead(map);
}
});
pipeline.addLast("InboundHandler2", new ChannelInboundHandlerAdapter() {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
log.info("InboundHandler2读入数据");
Map map = (Map) msg;
map.forEach((k,v)->{
System.out.println(k+"="+v);
});
ctx.fireChannelRead(msg);
}
});
}
相关文章
- Netty业务开发常见Bug解析
- Netty是如何断开连接的?
- Netty源码实战(十一) --- 设计模式的应用
- netty websocket协议开发
- netty 实现socket服务端编写
- 网络I/o编程模型10 netty介绍
- Netty 的 FastThreadLocal VS JAVA ThreadLocal
- Netty 服务端创建
- Netty学习之实战WebSocket框架
- Netty 系列六(编解码器).
- netty 解决TCP粘包与拆包问题(二)
- Netty系列之Netty百万级推送服务设计要点
- Netty客户端连接池ChannelPool应用 【支持https请求】
- BIO、NIO、AIO系列二:Netty