首先在第一个程序开始学习
Netty是一个基于NIO, 使用Reactor模式实现的网络通信框架.
于是我们通过Reactor模式, 按图索骥, 大概认识一下Netty的主要组件如下:
核心组件:
代码1: Server端 - 启动类
- package netty.discard;
-
- import io.netty.bootstrap.ServerBootstrap;
- import io.netty.channel.ChannelFuture;
- import io.netty.channel.ChannelInitializer;
- import io.netty.channel.ChannelOption;
- import io.netty.channel.nio.NioEventLoopGroup;
- import io.netty.channel.socket.SocketChannel;
- import io.netty.channel.socket.nio.NioServerSocketChannel;
-
- /**
- * Instruction:丢弃信息服务器
- * Author:@author MaLi
- */
- public class DiscardServer {
- private int port;
-
- public DiscardServer(int port) {
- this.port = port;
- }
-
- public void startServer() {
-
- //创建组装器: 配置Netty的服务器端组件
- ServerBootstrap serverBootstrap = new ServerBootstrap();
-
- //1, 创建事件轮询组: 其中的每一个线程 - EventLoop对应一个Reactor或者SunReactor, 这里采用多线程的Reactor模式, 所有设置了两个轮询组
- NioEventLoopGroup bossGroup = new NioEventLoopGroup(1);// 父轮询组: 用于查询 - 新连接事件
- NioEventLoopGroup workerGroup = new NioEventLoopGroup();//子轮询组: 用于查询 - 数据传输事件
- serverBootstrap.group(bossGroup, workerGroup); //由组装器设置两个轮询组
-
- //2, 创建通道类型并设置通道参数: 封装NIO中的Channel, 但是比Channel稍有区别(里面内置了PipeLine)
- NioServerSocketChannel socketChannel = new NioServerSocketChannel();
- //设置通道参数
- serverBootstrap.channel(socketChannel.getClass());
- serverBootstrap.localAddress(port);
- serverBootstrap.option(ChannelOption.SO_KEEPALIVE, true);
-
- //3, 设置Handler事件处理器
- serverBootstrap.childHandler(new ChannelInitializer
() { - @Override
- protected void initChannel(SocketChannel ch) throws Exception {
- ch.pipeline().addLast(new NettyDiscardHandler());
- }
- });
-
- try {
- //4, 绑定当前Channel到服务器端口 Create a new Channel and bind it.
- ChannelFuture channelFuture = serverBootstrap.bind().sync();//这里为什么创建一个Channel, 并绑定到服务器
- //关闭通道(为什么要关闭通道, 被关闭的是哪个通道 - ServerSocketChannel父通道, 父通道用于轮询新连接事件)
- // Returns the ChannelFuture which will be notified when this channel is closed. - 如果channel被关闭才会调用该回调
- // This method always returns the same future instance.
- // 5, 设置关闭channel时候的动作? --> 应用停止的时候父Channel才会被关闭, 释放掉底层的文件描述符
- channelFuture.channel().closeFuture().sync();
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }finally {
- //6, 关闭两个事件轮询组, 进一步释放资源.
- workerGroup.shutdownGracefully();
- bossGroup.shutdownGracefully();
- }
- }
- public static void main(String[] args) {
- DiscardServer server = new DiscardServer(8888);
- server.startServer();
- }
- }
代码2: Server端 - 处理器
- package netty.discard;
-
- import io.netty.channel.ChannelHandlerContext;
- import io.netty.channel.ChannelInboundHandlerAdapter;
-
- /**
- * Instruction:handler中的生命周期函数
- * Author:@author MaLi
- */
- public class NettyDiscardHandler extends ChannelInboundHandlerAdapter {
- // 如果有新连接被建立
- @Override
- public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
- System.out.println("NettyDiscardHandler registed");
- super.channelRegistered(ctx);
- }
-
- @Override
- public void channelActive(ChannelHandlerContext ctx) throws Exception {
- System.out.println("NettyDiscardHandler actived");
- super.channelActive(ctx);
- }
-
- @Override
- public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
- System.out.println("data read");
- super.channelRead(ctx, msg);
- }
-
- @Override
- public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
- System.out.println("data read completed");
- super.channelReadComplete(ctx);
- }
-
- @Override
- public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
- System.out.println("data reading exception caught");
- super.exceptionCaught(ctx, cause);
- }
- }
代码3: Client端
- package netty.discard;
-
- import java.io.IOException;
- import java.net.InetSocketAddress;
- import java.net.Socket;
-
- /**
- * Instruction:
- * Author:@author MaLi
- */
- public class DiscardClient {
- public static void main(String[] args) {
- Socket socket = new Socket();
- try {
- socket.connect(new InetSocketAddress("localhost", 8888)); //连接事件
- //socket.getOutputStream().write(1); // 数据发送事件
- socket.close();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- }