| package com.genersoft.iot.vmp.jt1078.codec.netty; | 
|   | 
| import com.genersoft.iot.vmp.jt1078.codec.decode.Jt808Decoder; | 
| import com.genersoft.iot.vmp.jt1078.codec.encode.Jt808Encoder; | 
| import com.genersoft.iot.vmp.jt1078.codec.encode.Jt808EncoderCmd; | 
| import com.genersoft.iot.vmp.jt1078.proc.factory.CodecFactory; | 
| import io.netty.bootstrap.ServerBootstrap; | 
| import io.netty.buffer.ByteBuf; | 
| import io.netty.buffer.Unpooled; | 
| import io.netty.channel.ChannelFuture; | 
| import io.netty.channel.ChannelInitializer; | 
| import io.netty.channel.EventLoopGroup; | 
| import io.netty.channel.nio.NioEventLoopGroup; | 
| import io.netty.channel.socket.nio.NioChannelOption; | 
| import io.netty.channel.socket.nio.NioServerSocketChannel; | 
| import io.netty.channel.socket.nio.NioSocketChannel; | 
| import io.netty.handler.codec.DelimiterBasedFrameDecoder; | 
| import io.netty.handler.timeout.IdleStateHandler; | 
| import io.netty.util.concurrent.Future; | 
| import org.slf4j.Logger; | 
| import org.slf4j.LoggerFactory; | 
|   | 
| import java.util.concurrent.TimeUnit; | 
|   | 
| /** | 
|  * @author QingtaiJiang | 
|  * @date 2023/4/27 18:01 | 
|  * @email qingtaij@163.com | 
|  */ | 
|   | 
| public class TcpServer { | 
|     private final static Logger log = LoggerFactory.getLogger(TcpServer.class); | 
|   | 
|     private final Integer port; | 
|     private boolean isRunning = false; | 
|     private EventLoopGroup bossGroup = null; | 
|     private EventLoopGroup workerGroup = null; | 
|   | 
|     private final ByteBuf DECODER_JT808 = Unpooled.wrappedBuffer(new byte[]{0x7e}); | 
|   | 
|     public TcpServer(Integer port) { | 
|         this.port = port; | 
|     } | 
|   | 
|     private void startTcpServer() { | 
|         try { | 
|             CodecFactory.init(); | 
|             this.bossGroup = new NioEventLoopGroup(); | 
|             this.workerGroup = new NioEventLoopGroup(); | 
|             ServerBootstrap bootstrap = new ServerBootstrap(); | 
|             bootstrap.channel(NioServerSocketChannel.class); | 
|             bootstrap.group(bossGroup, workerGroup); | 
|   | 
|             bootstrap.option(NioChannelOption.SO_BACKLOG, 1024) | 
|                     .option(NioChannelOption.SO_REUSEADDR, true) | 
|                     .childOption(NioChannelOption.TCP_NODELAY, true) | 
|                     .childHandler(new ChannelInitializer<NioSocketChannel>() { | 
|                         @Override | 
|                         public void initChannel(NioSocketChannel channel) { | 
|                             channel.pipeline() | 
|                                     .addLast(new IdleStateHandler(10, 0, 0, TimeUnit.MINUTES)) | 
|                                     .addLast(new DelimiterBasedFrameDecoder(1024 * 2, DECODER_JT808)) | 
|                                     .addLast(new Jt808Decoder()) | 
|                                     .addLast(new Jt808Encoder()) | 
|                                     .addLast(new Jt808EncoderCmd()) | 
|                                     .addLast(new Jt808Handler()); | 
|                         } | 
|                     }); | 
|             ChannelFuture channelFuture = bootstrap.bind(port).sync(); | 
|             // 监听设备TCP端口是否启动成功 | 
|             channelFuture.addListener(future -> { | 
|                 if (!future.isSuccess()) { | 
|                     log.error("Binding port:{} fail!  cause: {}", port, future.cause().getCause(), future.cause()); | 
|                 } | 
|             }); | 
|             log.info("服务:JT808 Server 启动成功, port:{}", port); | 
|             channelFuture.channel().closeFuture().sync(); | 
|         } catch (Exception e) { | 
|             log.warn("服务:JT808 Server 启动异常, port:{},{}", port, e.getMessage(), e); | 
|         } finally { | 
|             stop(); | 
|         } | 
|     } | 
|   | 
|     /** | 
|      * 开启一个新的线程,拉起来Netty | 
|      */ | 
|     public synchronized void start() { | 
|         if (this.isRunning) { | 
|             log.warn("服务:JT808 Server 已经启动, port:{}", port); | 
|             return; | 
|         } | 
|         this.isRunning = true; | 
|         new Thread(this::startTcpServer).start(); | 
|     } | 
|   | 
|     public synchronized void stop() { | 
|         if (!this.isRunning) { | 
|             log.warn("服务:JT808 Server 已经停止, port:{}", port); | 
|         } | 
|         this.isRunning = false; | 
|         Future<?> future = this.bossGroup.shutdownGracefully(); | 
|         if (!future.isSuccess()) { | 
|             log.warn("bossGroup 无法正常停止", future.cause()); | 
|         } | 
|         future = this.workerGroup.shutdownGracefully(); | 
|         if (!future.isSuccess()) { | 
|             log.warn("workerGroup 无法正常停止", future.cause()); | 
|         } | 
|         log.warn("服务:JT808 Server 已经停止, port:{}", port); | 
|     } | 
| } |