Netty(三)建立服务端

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014252478/article/details/82797019

1、服务端时序图:

2、编码流程:

  1. 创建ServerBootstrap实例
  2. 设置EventLoopGroup
  3. 设置创建的Channel类型
  4. option配置属性
  5. 设置Handler,处理请求
  6. 设置ChildHandler,处理对应channel的请求
  7. 通过bind创建Chnnel并绑定,启动服务
serverBootstrap = new ServerBootstrap();
eventLoopGroup = new NioEventLoopGroup();

serverBootstrap.group(eventLoopGroup)
               .channel(NioServerSocketChannel.class)
               .option(ChannelOption.SO_KEEPALIVE, true)
               .handler(new LoggingHandler(LogLevel.INFO));

 设置Handler,处理请求

 设置ChildHandler,处理对应channel的请求

 通过bind创建Chnnel并绑定,启动服务

 serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {

            @Override
            protected void initChannel(SocketChannel sc) throws Exception {
                sc.pipeline()
                        .addLast(new ProtocolDecoder(chargeDevice))
                        .addLast(new ProtocolEncoder())
                        .addLast(new IdleStateHandler(readerIdleTime, writerIdleTime, allIdleTime, TimeUnit.SECONDS))
                        .addLast(new MyInboundHandler(chargeDevice));
            }
        });
        this.channelFuture = serverBootstrap.bind(port).sync();

3、服务端重要组件

(1)ServerBootstrap
ServerBootstrap是Netty服务端的启动辅助类,提供一系列的方法用于设置服务端的参数和配置,简化开发。(衍生一点:ServerBootstrap的构造方法是无参的,因为参数太多所以采用了Builder模式)

继承自AbstractBootstrap,核心属性有childGroup和childHandler。

  • childGroup:负责调度和执行客户端的接入、网络读写事件的处理、用户自定义任务和定时任务的执行
  • childHandler:自定义的业务Handler

AbstractBootstrap核心属性有group和handler。

  • group:处理客户端的链接请求,并转交给childGroup(读取的数据是穿件的NioSocketChannel)

(2)Reactor线程池
Netty的Reactor线程池是EventLoopGroup,实际上是一个EventLoop的数组。

EventLoop的职责是处理所有注册到本线程多路复用器Selector上的Channel,Selector的轮训操作有EventLoop线程run方法驱动。

另外用户自定义的Task和定时任务Task也由统一的EventLoop负责处理。

(3)Channel
作为Nio服务,需要创建ServerSocketChannel,Netty对原生NIO类库做了封装,对应实现类为NioServerSocketChannel。

用户只需要制定Channel的实现类型,内部通过反射机制来创建对应的实例。

因为只在监听端口时创建,所以反射的性能影响并不大。

(4)ChannelPipeline
ChannelPipeline是网络事件处理的职责链,负责管理和执行ChannelHandler。网络事件以事件流的形式在ChannelPipeline中流转。

(5)ChannelHandler
ChannelHandler是提供给用户定制和扩展的关键接口,包括编解码,业务处理等都是通过ChannelHandler进行的。

(6)Selector
Selector轮训操作由NioEventLoop调度和执行,选择准备就绪的Channel集合。

(7)NioServerSocketChannel
绑定Server端地址的Server,读取客户端的链接请求(只有一个,在bind时创建)。

(8)NioSocketChannel
和客户端之间的链接。

4、实例

public class NettyServer {

    public void bind(int port){
        // 创建EventLoopGroup
        EventLoopGroup bossGroup = new NioEventLoopGroup();        //创建BOSS线程组 用于服务端接受客户端的连接
        EventLoopGroup workerGroup = new NioEventLoopGroup();      //创建WORK线程组 用于进行SocketChannel的网络读写

        try {
            // 创建ServerBootStrap实例
            // ServerBootstrap 用于启动NIO服务端的辅助启动类,目的是降低服务端的开发复杂度
            ServerBootstrap b = new ServerBootstrap();
            // 绑定Reactor线程池
            b.group(bossGroup, workerGroup)
                    // 设置并绑定服务端Channel
                    // 指定所使用的NIO传输的Channel
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    .handler(new LoggingServerHandler())
                    .childHandler(new ChannelInitializer(){

                        @Override
                        protected void initChannel(Channel ch) throws Exception {
                            //do something
                        }
                    });

            // 绑定端口,同步等待成功
            ChannelFuture future = b.bind(port).sync();
            // 等待服务端监听端口关闭
            future.channel().closeFuture().sync();

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            // 优雅地关闭
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    private class LoggingServerHandler extends ChannelInboundHandlerAdapter{
        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            System.out.println("loggin-channelActive");
        }

        @Override
        public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
            System.out.println("loggin-channelRegistered");
        }

        @Override
        public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
            System.out.println("loggin-handlerAdded");
        }
    }

    public static void main(String[] args){
            new NettyServer().bind(8899);
    }
}

猜你喜欢

转载自blog.csdn.net/u014252478/article/details/82797019