目录
目标
Netty版本
Netty官方API
实战
Netty服务器
入栈ChannelHandler读入数据顺序案例
出栈ChannelHandler写出数据顺序案例
ChannelHandlerContext和NioSocketChannel写入数据时有什么不同
Pipeline添加多个ChannelHandler有什么意义
io.netty
netty-all
4.1.87.Final
Netty API Reference (4.1.89.Final)https://netty.io/4.1/api/index.html
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() {
@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先执行。
*/
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);
}
});
}
/**
* 出栈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写入数据以后,调用顺序:从当前这个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添加多个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 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);
}
});
}