一、基本概念
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();}
}