package com.njcn.gather.detection.util.socket.service;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.ServerSocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.CharsetUtil;


/**
 * @Description: NettyServer 心跳检测服务端
 *
 *   Netty心跳检测与断线重连
 *   需求：
 *   1、客户端利用空闲状态给服务端发送心跳ping命令，保持长连接不被关闭；
 *   2、服务端如果超过指定的时间没有收到客户端心跳，则关闭连接；
 *   3、服务端关闭连接触发客户端的channelInactive方法，在此方法中进行重连；
 * @Author: wr
 * @Date: 2024/12/10 14:18
 */
public class NettyServer {

    public static final int port = 8574;

    public static void main(String[] args) {
        NettyServer nettyServer = new NettyServer();
        nettyServer.runSource();
    }


    public static void sourceMain(String[] args) {
        NettyServer nettyServer = new NettyServer();
        nettyServer.runDev();
    }


    private void runSource() {
        NioEventLoopGroup boss = new NioEventLoopGroup(1);
        NioEventLoopGroup work = new NioEventLoopGroup();
        try {
            ServerBootstrap bootstrap = new ServerBootstrap().group(boss, work);
            bootstrap.channel(NioServerSocketChannel.class)
                     //这个处理器可以不写
                    .handler(new ChannelInitializer<ServerSocketChannel>() {
                        @Override
                        protected void initChannel(ServerSocketChannel ch) {
                            System.out.println("源通讯服务正在启动中......");
                        }
                    })
                    //业务处理
                    .childHandler(new ChannelInitializer<NioSocketChannel>() {
                        @Override
                        protected void initChannel(NioSocketChannel ch) {
                                ch.pipeline()
                                        //空闲状态的handler
                                        // 添加LineBasedFrameDecoder来按行分割数据
                                        .addLast(new LineBasedFrameDecoder(10240*2))
                                        .addLast(new StringDecoder(CharsetUtil.UTF_8))
                                        .addLast(new StringEncoder(CharsetUtil.UTF_8))
                                        .addLast(new DevNettyServerHandler());
                        }
                    });

            ChannelFuture future = bootstrap.bind(port).sync();

            future.addListener(f -> {
                if (future.isSuccess()) {
                    System.out.println("源通讯服务启动成功");
                } else {
                    System.out.println("源通讯服务启动失败");
                }
            });
            future.channel().closeFuture().sync();

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            boss.shutdownGracefully();
            work.shutdownGracefully();
        }
    }


    private void runDev() {
        NioEventLoopGroup boss = new NioEventLoopGroup(1);
        NioEventLoopGroup work = new NioEventLoopGroup();
        try {
            ServerBootstrap bootstrap = new ServerBootstrap().group(boss, work);
            bootstrap.channel(NioServerSocketChannel.class)
                    //这个处理器可以不写
                    .handler(new ChannelInitializer<ServerSocketChannel>() {
                        @Override
                        protected void initChannel(ServerSocketChannel ch) {
                            System.out.println("设备通讯服务正在启动中......");
                        }
                    })
                    //业务处理
                    .childHandler(new ChannelInitializer<NioSocketChannel>() {
                        @Override
                        protected void initChannel(NioSocketChannel ch) {
                            ch.pipeline()
                                    //空闲状态的handler
                                    // 添加LineBasedFrameDecoder来按行分割数据
                                    .addLast(new LineBasedFrameDecoder(10240*2))
                                    .addLast(new StringDecoder(CharsetUtil.UTF_8))
                                    .addLast(new StringEncoder(CharsetUtil.UTF_8))
                                    .addLast(new SourceNettyServerHandler());
                        }
                    });

            ChannelFuture future = bootstrap.bind(port).sync();

            future.addListener(f -> {
                if (future.isSuccess()) {
                    System.out.println("设备通讯服务启动成功");
                } else {
                    System.out.println("设备通讯服务启动失败");
                }
            });
            future.channel().closeFuture().sync();

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            boss.shutdownGracefully();
            work.shutdownGracefully();
        }
    }

}
