Netty(三)建立服务端

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);
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Netty是一种基于事件驱动的网络应用框架,可以用于开发高性能、可扩展的服务器和客户端应用程序。MQTT是一种轻量级的消息传输协议,常用于物联网设备之间的通信。 要在Netty MQTT服务端获取topic,可以按照以下步骤进行: 1. 创建Netty服务端:使用Netty框架创建一个MQTT服务器。可以通过继承SimpleChannelInboundHandler类,重写channelRead0方法来处理收到的消息。 2. 配置MQTT参数:在服务端配置MQTT参数,例如端口号、超时时间等。 3. 处理连接请求:当客户端发送连接请求时,服务端可以根据需要进行一些认证或授权操作,并向客户端发送连接响应。 4. 订阅topic:在连接建立后,客户端可以发送订阅请求,服务端需要解析订阅请求,并确保订阅成功。可以在channelRead0方法中获取消息的topic。 5. 处理发布消息:当客户端发布消息时,服务端可以通过channelRead0方法获取消息的topic和内容,并进行相应的处理逻辑。 6. 反馈响应结果:在处理完消息后,服务端可以向客户端发送响应信息以确认消息的接收状态。 通过以上步骤,服务端可以获取到客户端发送的订阅请求和发布消息的topic。在channelRead0方法中,可以使用msg.topic()方法获取消息的topic。根据具体需求,服务端可以对不同的topic做出不同的处理操作。 总之,通过使用Netty框架和Mqtt协议,我们可以轻松地搭建一个支持获取topic的MQTT服务端
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值