spring boot 集成netty,及其一些基本概念
一、基本概念
1、channel:通道,入站或者出站数据的载体
2、ChannelHandler:通道处理器,业务逻辑写在这里面,netty 5版本将入战和出站合并成了ChannelHandler
3、ChannelPipeline:通道里的管道,是一个或者多个ChannelHandler链的容器,当channel被创建时,会为该Channel自动分配一个ChannelPipeline,ChannelPipeline中可以放多个ChannelHandler。
4、ChannelHandlerContext:通道处理器上下文,代表了ChannelHandler和ChannelPipeline的关联关系,每当有ChannelHandler被添加到ChannelPipeline时就会创建一个ChannelHandlerContext。ChannelHandlerContext的主要功能是管理它所关联的ChannelHandler和在同一个ChannelPipeline中其他的ChannelHandler之间的交互。
5、ChannelHandlerAdapter:通道处理器的适配器,提供了入站和出站ChannelHandler的基本实现。
6、EventLoop与EventLoopGroup:称为事件循环,用来运行连着周期内发生的事件的。EventLoopGroup为每个新创建的Channel分配一个EventLoop。多个Channel可以共享一个EventLoop。
7、SimpleChannelInboundHandler:可以用来接收解码消息,无需手动释放资源。
8、引导:作用是创建Channel组装成可运行的程序。分为客户端引导和服务端引导。客户端引导:为客户端应用程序创建Channel当调用bind()或者connect()方法时就会创建一个Channel。服务器引导:当bind()方法被调用时会创建一个ServerChannel,当有客户端连接并且服务器端接受时,ServerChannel会创建相应的Channel进行通信。
9、ChannelInitializer:通道Channel初始化时调用。
10、入站和出站:入站是指数据从网络层流向你的应用程序,出战是指数据从应用程序流向网络层。在ChannelPipeline的流向,入站是从头到尾,出站是从尾流向头部。
11、注意:ChannelHandler的实现类,如果被标记为@Sharable,则代码该处理器可以被添加到多个ChannelPipeline中去。
二、搭建一个简单的客户端和服务端
1、安装依赖
<dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>5.0.0.Alpha2</version>
</dependency>
2、客户端
2.1 新建处理器类:EchoClientHandler
@ChannelHandler.Sharable
public class EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf> {@Overridepublic void channelActive(ChannelHandlerContext ctx){ctx.writeAndFlush(Unpooled.copiedBuffer("Netty rocks!", CharsetUtil.UTF_8));}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg){ByteBuf in = (ByteBuf) msg;System.out.println("Client received: " + in.toString(CharsetUtil.UTF_8));}@Overrideprotected void messageReceived(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) throws Exception {}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause){cause.printStackTrace();ctx.close();}
}
2.2 新建客户端引导
public class EchoClient {private final String host;private final int port;public EchoClient(String host, int port) {this.host = host;this.port = port;}public void start() throws Exception {EventLoopGroup group = new NioEventLoopGroup();try {Bootstrap bootstrap = new Bootstrap();bootstrap.group(group).channel(NioSocketChannel.class).remoteAddress(new InetSocketAddress(host, port)).handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(new EchoClientHandler());}});ChannelFuture future = bootstrap.connect().sync();future.channel().closeFuture().sync();}finally {group.shutdownGracefully().sync();}}public static void main(String[] args) throws Exception {new EchoClient("127.0.0.1", 2221).start();}}
3、服务器端
3.1 新建服务器端ChannelHandler
@ChannelHandler.Sharable
//@ChannelHandler.Sharable
public class EchoServerHandler extends SimpleChannelInboundHandler {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg){ByteBuf in = (ByteBuf) msg;System.out.println("Server received: " + in.toString(CharsetUtil.UTF_8));ctx.write(in);}@Overridepublic void channelReadComplete(ChannelHandlerContext ctx){ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause){cause.printStackTrace();ctx.close();}@Overrideprotected void messageReceived(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {}
}
3.2 新建服务器端引导
public class EchoServer {private final int port;public EchoServer(int port) {this.port = port;}public void start() throws Exception {final EchoServerHandler serverHandler = new EchoServerHandler();EventLoopGroup group = new NioEventLoopGroup();try {ServerBootstrap b = new ServerBootstrap();b.group(group).channel(NioServerSocketChannel.class).localAddress(new InetSocketAddress(port)).childHandler(new ChannelInitializer<SocketChannel>() {@Overridepublic void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(serverHandler);}});System.out.println("监听端口");ChannelFuture f=b.bind().sync();System.out.println("服务端关闭");f.channel().closeFuture().sync();}finally {group.shutdownGracefully().sync();}}public static void main(String[] args) throws Exception {new EchoServer(2221).start();}
}