diff --git a/detection/pom.xml b/detection/pom.xml
new file mode 100644
index 00000000..92441418
--- /dev/null
+++ b/detection/pom.xml
@@ -0,0 +1,41 @@
+
+
+ 4.0.0
+
+ com.njcn.gather
+ CN_Gather
+ 1.0.0
+
+
+ detection
+
+
+
+ com.njcn
+ njcn-common
+ 0.0.1
+
+
+
+ com.njcn
+ mybatis-plus
+ 0.0.1
+
+
+
+ com.njcn
+ spingboot2.3.12
+ 2.3.12
+
+
+
+ io.netty
+ netty-all
+ 4.1.68.Final
+
+
+
+
+
\ No newline at end of file
diff --git a/detection/src/main/java/com/njcn/gather/detection/controller/PunctualityController.java b/detection/src/main/java/com/njcn/gather/detection/controller/PunctualityController.java
new file mode 100644
index 00000000..b1a14f32
--- /dev/null
+++ b/detection/src/main/java/com/njcn/gather/detection/controller/PunctualityController.java
@@ -0,0 +1,41 @@
+package com.njcn.gather.detection.controller;
+
+import com.njcn.common.pojo.annotation.OperateInfo;
+import com.njcn.common.pojo.enums.response.CommonResponseEnum;
+import com.njcn.common.pojo.response.HttpResult;
+import com.njcn.web.controller.BaseController;
+import com.njcn.web.utils.HttpResultUtil;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author wr
+ * @description
+ * @date 2024/12/10 14:25
+ */
+@Slf4j
+@Api(tags = "守时检测")
+@RestController
+@RequestMapping("/punctuality")
+@RequiredArgsConstructor
+public class PunctualityController extends BaseController {
+
+// private final PunctualityService punctualityService;
+
+ @OperateInfo
+ @PostMapping("/deliveryTime")
+ @ApiOperation("下发守时检测")
+ @ApiImplicitParam(name = "queryParam", value = "查询参数", required = true)
+ public HttpResult> list(@RequestBody Object param) {
+ String methodDescribe = getMethodDescribe("list");
+// punctualityService.triggerTimeMark();
+ return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, methodDescribe);
+ }
+}
diff --git a/detection/src/main/java/com/njcn/gather/detection/service/PreDetectionService.java b/detection/src/main/java/com/njcn/gather/detection/service/PreDetectionService.java
new file mode 100644
index 00000000..d7c6dadc
--- /dev/null
+++ b/detection/src/main/java/com/njcn/gather/detection/service/PreDetectionService.java
@@ -0,0 +1,32 @@
+package com.njcn.gather.detection.service;
+
+/**
+ * @author wr
+ * @description 预检测流程
+ * @date 2024/12/10 13:44
+ */
+public interface PreDetectionService {
+
+ /**
+ * 源通讯校验
+ */
+ void sourceCommunicationCheck();
+
+ /**
+ * 装置通讯校验
+ */
+ void deviceCommunicationCheck();
+
+ /**
+ * 协议校验
+ */
+ void agreementCheck();
+
+ /**
+ * 相序校验
+ */
+ void phaseSequenceCheck();
+
+
+
+}
diff --git a/detection/src/main/java/com/njcn/gather/detection/service/PunctualityService.java b/detection/src/main/java/com/njcn/gather/detection/service/PunctualityService.java
new file mode 100644
index 00000000..1369ae90
--- /dev/null
+++ b/detection/src/main/java/com/njcn/gather/detection/service/PunctualityService.java
@@ -0,0 +1,14 @@
+package com.njcn.gather.detection.service;
+
+/**
+ * @Description: 守时检测流程
+ * @Author: wr
+ * @Date: 2024/12/10 14:23
+ */
+public interface PunctualityService {
+
+ /**
+ * 触发时间标识
+ */
+ void triggerTimeMark();
+}
diff --git a/detection/src/main/java/com/njcn/gather/detection/util/scoket/NettyClient.java b/detection/src/main/java/com/njcn/gather/detection/util/scoket/NettyClient.java
new file mode 100644
index 00000000..21b8b41b
--- /dev/null
+++ b/detection/src/main/java/com/njcn/gather/detection/util/scoket/NettyClient.java
@@ -0,0 +1,132 @@
+package com.njcn.gather.detection.util.scoket;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import io.netty.bootstrap.Bootstrap;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelFutureListener;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.EventLoop;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.nio.NioSocketChannel;
+import io.netty.handler.codec.http.DefaultHttpHeaders;
+import io.netty.handler.codec.http.HttpObjectAggregator;
+import io.netty.handler.codec.http.HttpResponseDecoder;
+import io.netty.handler.codec.http.HttpServerCodec;
+import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
+import io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
+import io.netty.handler.codec.http.websocketx.WebSocketClientProtocolHandler;
+import io.netty.handler.codec.http.websocketx.WebSocketVersion;
+import io.netty.handler.codec.string.StringDecoder;
+import io.netty.handler.codec.string.StringEncoder;
+import io.netty.handler.timeout.IdleStateHandler;
+import io.netty.util.CharsetUtil;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @Description: 心跳检测服务端 对应的服务端在netty-server 包下的NettyClient
+ * @Author: wr
+ * @Date: 2024/12/10 14:16
+ */
+public class NettyClient {
+
+ private static Bootstrap bootstrap;
+
+ public static void socketClient(String msg) {
+ try {
+ NioEventLoopGroup group = new NioEventLoopGroup();
+ if (ObjectUtil.isNull(bootstrap)) {
+ bootstrap = new Bootstrap();
+ bootstrap.group(group)
+ .channel(NioSocketChannel.class)
+ .handler(new ChannelInitializer() {
+ @Override
+ protected void initChannel(NioSocketChannel ch) {
+ ch.pipeline()
+ //空闲状态的handler
+// .addLast(new IdleStateHandler(0, 5, 0, TimeUnit.SECONDS))
+ .addLast(new StringDecoder(CharsetUtil.UTF_8))
+ .addLast(new StringEncoder(CharsetUtil.UTF_8))
+ .addLast(new NettyClientHandler());
+ }
+ });
+ }
+
+ //连接
+ connect(msg);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 重连方法
+ */
+ public static void connect(String msg) {
+ try {
+ bootstrap.connect("127.0.0.1", 8787).sync()
+ .addListener((ChannelFutureListener) ch -> {
+ if (!ch.isSuccess()) {
+ ch.channel().close();
+ final EventLoop loop = ch.channel().eventLoop();
+ loop.schedule(() -> {
+ System.err.println("服务端链接不上,开始重连操作...");
+ //重连
+ connect(msg);
+ }, 3L, TimeUnit.SECONDS);
+ } else {
+ if (StrUtil.isNotBlank(msg)) {
+ ch.channel().writeAndFlush(msg);
+ }
+ System.out.println("服务端链接成功...");
+ }
+ });
+
+ } catch (Exception e) {
+ System.out.println(e.getMessage());
+ try {
+ Thread.sleep(3000L);
+ } catch (InterruptedException ex) {
+ ex.printStackTrace();
+ }
+ //再重连
+ connect(msg);
+ }
+ }
+
+
+ /**
+ * 重连方法
+ */
+ public static void connect() {
+ try {
+ bootstrap.connect("127.0.0.1", 8787).sync()
+ .addListener((ChannelFutureListener) ch -> {
+ if (!ch.isSuccess()) {
+ ch.channel().close();
+ final EventLoop loop = ch.channel().eventLoop();
+ loop.schedule(() -> {
+ System.err.println("服务端链接不上,开始重连操作...");
+ //重连
+ connect();
+ }, 3L, TimeUnit.SECONDS);
+ } else {
+ ch.channel().writeAndFlush("ping");
+ System.out.println("服务端链接成功...");
+ }
+ });
+ } catch (Exception e) {
+ System.out.println(e.getMessage());
+ try {
+ Thread.sleep(3000L);
+ } catch (InterruptedException ex) {
+ ex.printStackTrace();
+ }
+ //再重连
+ connect();
+ }
+ }
+}
diff --git a/detection/src/main/java/com/njcn/gather/detection/util/scoket/NettyClientHandler.java b/detection/src/main/java/com/njcn/gather/detection/util/scoket/NettyClientHandler.java
new file mode 100644
index 00000000..b185364f
--- /dev/null
+++ b/detection/src/main/java/com/njcn/gather/detection/util/scoket/NettyClientHandler.java
@@ -0,0 +1,95 @@
+package com.njcn.gather.detection.util.scoket;
+
+import com.njcn.gather.detection.util.webscoket.UserSessionManager;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
+import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
+import io.netty.handler.timeout.IdleState;
+import io.netty.handler.timeout.IdleStateEvent;
+
+import java.util.Scanner;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @Description: 客户端业务处理
+ * @Author: wr
+ * @Date: 2024/12/10 14:16
+ */
+public class NettyClientHandler extends SimpleChannelInboundHandler {
+
+ /**
+ * 当通道进行连接时推送消息
+ * @param ctx
+ */
+ @Override
+ public void channelActive(ChannelHandlerContext ctx) throws Exception {
+ System.out.println("通道已建立" + ctx.channel().remoteAddress());
+ }
+
+ /**
+ * 处理服务端消息消息信息
+ */
+ @Override
+ protected void channelRead0(ChannelHandlerContext ctx, String msg) {
+ if(msg.endsWith("结束")){
+ Channel userId = UserSessionManager.getChannelByUserId("userId");
+ TextWebSocketFrame wd1 = new TextWebSocketFrame("流程结束");
+ userId.writeAndFlush(wd1);
+ ctx.close();
+ }else{
+ System.out.println("服务端消息 == " + msg);
+ Scanner scanner = new Scanner(System.in);
+ System.out.print("一个信息返回客户端:");
+ String text = scanner.nextLine();
+ ctx.writeAndFlush(text);
+ }
+
+ }
+
+ /**
+ * 当通道断线时,支持重连
+ * @param ctx
+ */
+ @Override
+ public void channelInactive(ChannelHandlerContext ctx) {
+// System.out.println("断线了......" + ctx.channel());
+// ctx.channel().eventLoop().schedule(() -> {
+// System.out.println("断线重连......");
+// //重连
+// NettyClient.connect();
+// }, 3L, TimeUnit.SECONDS);
+ }
+
+ /**
+ * 用户事件的回调方法(自定义事件用于心跳机制)
+ *
+ * @param ctx
+ * @param evt
+ */
+ @Override
+ public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
+ //如果是空闲状态事件
+// if (evt instanceof IdleStateEvent) {
+// if (((IdleStateEvent) evt).state() == IdleState.WRITER_IDLE) {
+// System.out.println("空闲" + ctx.channel().id());
+// //发送ping 保持心跳链接
+// TextWebSocketFrame resp = new TextWebSocketFrame(ctx.channel().id() + " ping");
+// ctx.writeAndFlush(resp);
+// }
+// }else {
+// userEventTriggered(ctx,evt);
+// }
+ }
+
+ @Override
+ public void handlerAdded(ChannelHandlerContext ctx) {
+ System.out.println("有通道接入" + ctx.channel());
+ }
+ @Override
+ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
+ cause.printStackTrace();
+ ctx.close();
+ }
+
+}
diff --git a/detection/src/main/java/com/njcn/gather/detection/util/scoket/NettyServer.java b/detection/src/main/java/com/njcn/gather/detection/util/scoket/NettyServer.java
new file mode 100644
index 00000000..99ed8572
--- /dev/null
+++ b/detection/src/main/java/com/njcn/gather/detection/util/scoket/NettyServer.java
@@ -0,0 +1,66 @@
+package com.njcn.gather.detection.util.scoket;
+
+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;
+
+
+/**
+ * @Description: NettyServer 心跳检测服务端
+ *
+ * Netty心跳检测与断线重连
+ * 需求:
+ * 1、客户端利用空闲状态给服务端发送心跳ping命令,保持长连接不被关闭;
+ * 2、服务端如果超过指定的时间没有收到客户端心跳,则关闭连接;
+ * 3、服务端关闭连接触发客户端的channelInactive方法,在此方法中进行重连;
+ * @Author: wr
+ * @Date: 2024/12/10 14:18
+ */
+public class NettyServer {
+
+ public static final int port = 8787;
+
+ public static void main(String[] args) {
+ NettyServer nettyServer = new NettyServer();
+ nettyServer.run();
+ }
+
+
+ private void run() {
+ NioEventLoopGroup boss = new NioEventLoopGroup(1);
+ NioEventLoopGroup work = new NioEventLoopGroup();
+ try {
+ ServerBootstrap bootstrap = new ServerBootstrap().group(boss, work);
+ bootstrap.channel(NioServerSocketChannel.class)
+ //这个处理器可以不写
+ .handler(new ChannelInitializer() {
+ @Override
+ protected void initChannel(ServerSocketChannel ch) {
+ System.out.println("服务正在启动中......");
+ }
+ })
+ //业务处理
+ .childHandler(NettyServerChannelInitializer.INSTANCE);
+
+ 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();
+ }
+ }
+}
diff --git a/detection/src/main/java/com/njcn/gather/detection/util/scoket/NettyServerChannelInitializer.java b/detection/src/main/java/com/njcn/gather/detection/util/scoket/NettyServerChannelInitializer.java
new file mode 100644
index 00000000..7ef70d17
--- /dev/null
+++ b/detection/src/main/java/com/njcn/gather/detection/util/scoket/NettyServerChannelInitializer.java
@@ -0,0 +1,35 @@
+package com.njcn.gather.detection.util.scoket;
+
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.socket.nio.NioSocketChannel;
+import io.netty.handler.codec.string.StringDecoder;
+import io.netty.handler.codec.string.StringEncoder;
+import io.netty.handler.timeout.IdleStateHandler;
+import io.netty.util.CharsetUtil;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @Description: 服务端初始化配置
+ * @Author: wr
+ * @Date: 2024/12/10 14:18
+ */
+@ChannelHandler.Sharable
+public class NettyServerChannelInitializer extends ChannelInitializer {
+
+ public static final NettyServerChannelInitializer INSTANCE = new NettyServerChannelInitializer();
+
+ @Override
+ protected void initChannel(NioSocketChannel ch) {
+ ch.pipeline()
+ //空闲状态的处理器
+// .addLast(new IdleStateHandler(10, 0, 0, TimeUnit.SECONDS))
+ .addLast(new StringDecoder(CharsetUtil.UTF_8))
+ .addLast(new StringEncoder(CharsetUtil.UTF_8))
+ .addLast(NettyServerHandler.INSTANCE);
+ }
+
+
+}
diff --git a/detection/src/main/java/com/njcn/gather/detection/util/scoket/NettyServerHandler.java b/detection/src/main/java/com/njcn/gather/detection/util/scoket/NettyServerHandler.java
new file mode 100644
index 00000000..2a931c06
--- /dev/null
+++ b/detection/src/main/java/com/njcn/gather/detection/util/scoket/NettyServerHandler.java
@@ -0,0 +1,71 @@
+package com.njcn.gather.detection.util.scoket;
+
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
+import io.netty.handler.timeout.IdleState;
+import io.netty.handler.timeout.IdleStateEvent;
+import io.netty.util.ReferenceCountUtil;
+
+import java.util.Scanner;
+
+/**
+ * @Description: 客户端业务处理
+ * @Author: wr
+ * @Date: 2024/12/10 14:18
+ */
+@ChannelHandler.Sharable
+public class NettyServerHandler extends SimpleChannelInboundHandler {
+
+ public static final NettyServerHandler INSTANCE = new NettyServerHandler();
+
+ /**
+ * @Description: 当通道进行连接时推送消息
+ * @Author: wr
+ * @Date: 2024/12/10 14:19
+ */
+ @Override
+ public void channelActive(ChannelHandlerContext ctx) throws Exception {
+ super.channelActive(ctx);
+ }
+
+ /**
+ * 处理消息信息
+ */
+ @Override
+ public void channelRead0(ChannelHandlerContext ctx, String msg) {
+ Channel channel = ctx.channel();
+ System.out.println("socket客户端接收成功:"+msg);
+ if(msg.endsWith("结束")) {
+ channel.writeAndFlush("socket指令结果:"+msg);
+ }else{
+ channel.writeAndFlush("socket指令结果:成功指令");
+
+ }
+ }
+
+ @Override
+ public void handlerAdded(ChannelHandlerContext ctx) {
+ System.out.println("有新连接加入了++++......" + ctx.channel());
+ }
+
+ /**
+ * 用户事件的回调方法(自定义事件用于心跳机制)
+ */
+ @Override
+ public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
+ //空闲状态的事件
+// if (evt instanceof IdleStateEvent) {
+// IdleStateEvent event = (IdleStateEvent) evt;
+// System.out.println(event.state() + ">>>" + ctx.channel().id());
+// //已经10秒钟没有读时间了
+// if (event.state().equals(IdleState.READER_IDLE)){
+// // 心跳包丢失,10秒没有收到客户端心跳 (断开连接)
+// ctx.channel().close().sync();
+// System.out.println("已与 "+ctx.channel().remoteAddress()+" 断开连接");
+// }
+// }
+ }
+
+}
diff --git a/detection/src/main/java/com/njcn/gather/detection/util/webscoket/UserSessionManager.java b/detection/src/main/java/com/njcn/gather/detection/util/webscoket/UserSessionManager.java
new file mode 100644
index 00000000..e9992942
--- /dev/null
+++ b/detection/src/main/java/com/njcn/gather/detection/util/webscoket/UserSessionManager.java
@@ -0,0 +1,23 @@
+package com.njcn.gather.detection.util.webscoket;
+
+import io.netty.channel.Channel;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class UserSessionManager {
+ private static final Map userSessions = new ConcurrentHashMap<>();
+
+ public static void addUser(String userId, Channel channel) {
+ userSessions.put(userId, channel);
+ }
+
+ public static void removeUser(String userId) {
+ userSessions.remove(userId);
+ }
+
+ public static Channel getChannelByUserId(String userId) {
+ return userSessions.get(userId);
+ }
+}
+
\ No newline at end of file
diff --git a/detection/src/main/java/com/njcn/gather/detection/util/webscoket/WebSocketHandler.java b/detection/src/main/java/com/njcn/gather/detection/util/webscoket/WebSocketHandler.java
new file mode 100644
index 00000000..2c2a3dcb
--- /dev/null
+++ b/detection/src/main/java/com/njcn/gather/detection/util/webscoket/WebSocketHandler.java
@@ -0,0 +1,74 @@
+package com.njcn.gather.detection.util.webscoket;
+
+import com.njcn.gather.detection.util.scoket.NettyClient;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
+import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
+
+import java.util.Map;
+
+
+/**
+ * @Description: 泛型 代表的是处理数据的单位
+ * TextWebSocketFrame : 文本信息帧
+ * @Author: wr
+ * @Date: 2024/12/10 13:56
+ */
+public class WebSocketHandler extends SimpleChannelInboundHandler {
+
+
+ @Override
+ public void channelActive(ChannelHandlerContext ctx) throws Exception {
+ System.out.println("成功连接");
+ ctx.writeAndFlush("22222222222222222222");
+ }
+
+ @Override
+ protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) {
+ System.out.println("服务端消息 == " + msg.text());
+// Channel userId = UserSessionManager.getChannelByUserId("userId");
+// TextWebSocketFrame wd1 = new TextWebSocketFrame("------------------cs");
+// userId.writeAndFlush(wd1);
+ if(msg.text().equals("下发指令")){
+ NettyClient.socketClient(msg.text());
+ }
+
+ //可以直接调用text 拿到文本信息帧中的信息
+ Channel channel = ctx.channel();
+ TextWebSocketFrame resp = new TextWebSocketFrame(msg.text());
+ channel.writeAndFlush(resp);
+ }
+
+ @Override
+ public void handlerAdded(ChannelHandlerContext ctx) {
+ String userId = "userId";
+ UserSessionManager.addUser(userId, ctx.channel());
+ System.out.println("有新的连接接入:"+ctx);
+ }
+
+ @Override
+ public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
+ // 假设用户 ID 是从某个地方获取的,这里简单示例为 "userId"
+ String userId = "userId";
+ UserSessionManager.removeUser(userId);
+ System.out.println("有连接退出: " + ctx);
+ }
+
+ @Override
+ public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
+ //空闲状态的事件
+// if (evt instanceof IdleStateEvent) {
+// IdleStateEvent event = (IdleStateEvent) evt;
+// System.out.println(event.state() + ">>>" + ctx.channel().id());
+// //已经10秒钟没有读时间了
+// if (event.state().equals(IdleState.READER_IDLE)){
+// // 心跳包丢失,10秒没有收到客户端心跳 (断开连接)
+// ctx.channel().close().sync();
+// System.out.println("已与 "+ctx.channel().remoteAddress()+" 断开连接");
+// }
+// }
+ }
+}
+
diff --git a/detection/src/main/java/com/njcn/gather/detection/util/webscoket/WebSocketInitializer.java b/detection/src/main/java/com/njcn/gather/detection/util/webscoket/WebSocketInitializer.java
new file mode 100644
index 00000000..8c3eb10b
--- /dev/null
+++ b/detection/src/main/java/com/njcn/gather/detection/util/webscoket/WebSocketInitializer.java
@@ -0,0 +1,42 @@
+package com.njcn.gather.detection.util.webscoket;
+
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.ChannelPipeline;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.handler.codec.http.HttpObjectAggregator;
+import io.netty.handler.codec.http.HttpResponseDecoder;
+import io.netty.handler.codec.http.HttpServerCodec;
+import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
+import io.netty.handler.stream.ChunkedWriteHandler;
+
+/**
+ * @Description: webSocket服务端自定义配置
+ * @Author: wr
+ * @Date: 2024/12/10 14:20
+ */
+public class WebSocketInitializer extends ChannelInitializer {
+ @Override
+ protected void initChannel(SocketChannel ch) throws Exception {
+ ChannelPipeline pipeline = ch.pipeline();
+ //设置心跳机制
+// ch.pipeline().addLast(new IdleStateHandler(5, 0, 0));
+ //增加编解码器 的另一种方式
+ pipeline.addLast(new HttpServerCodec());
+ pipeline.addLast(new HttpResponseDecoder());
+ //块方式写的处理器 适合处理大数据
+ pipeline.addLast(new ChunkedWriteHandler());
+ //聚合
+ pipeline.addLast(new HttpObjectAggregator(512 * 1024));
+ /*
+ * 这个时候 我们需要声明我们使用的是 websocket 协议
+ * netty为websocket也准备了对应处理器 设置的是访问路径
+ * 这个时候我们只需要访问 ws://127.0.0.1:7777/hello 就可以了
+ * 这个handler是将http协议升级为websocket 并且使用 101 作为响应码
+ * */
+ pipeline.addLast(new WebSocketServerProtocolHandler("/hello"));
+ pipeline.addLast(new WebSocketHandler());
+
+ }
+
+}
+
diff --git a/detection/src/main/java/com/njcn/gather/detection/util/webscoket/WebSocketService.java b/detection/src/main/java/com/njcn/gather/detection/util/webscoket/WebSocketService.java
new file mode 100644
index 00000000..43609ef7
--- /dev/null
+++ b/detection/src/main/java/com/njcn/gather/detection/util/webscoket/WebSocketService.java
@@ -0,0 +1,49 @@
+package com.njcn.gather.detection.util.webscoket;
+
+
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelOption;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.nio.NioServerSocketChannel;
+import io.netty.handler.logging.LoggingHandler;
+
+
+/**
+ * @Description: websocket服务端
+ * @Author: wr
+ * @Date: 2024/12/10 13:59
+ */
+public class WebSocketService {
+
+
+ public static void main(String[] args) {
+ //可以自定义线程的数量
+ EventLoopGroup bossGroup = new NioEventLoopGroup();
+ // 默认创建的线程数量 = CPU 处理器数量 *2
+ EventLoopGroup workerGroup = new NioEventLoopGroup();
+
+ ServerBootstrap serverBootstrap = new ServerBootstrap();
+ serverBootstrap.group(bossGroup, workerGroup)
+ .channel(NioServerSocketChannel.class)
+ .handler(new LoggingHandler())
+ //当前连接被阻塞的时候,BACKLOG代表的事 阻塞队列的长度
+ .option(ChannelOption.SO_BACKLOG, 128)
+ //设置连接保持为活动状态
+ .childOption(ChannelOption.SO_KEEPALIVE, true)
+ .childHandler(new WebSocketInitializer());
+
+ try {
+ ChannelFuture future = serverBootstrap.bind(7777).sync();
+ future.channel().closeFuture().sync();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ } finally {
+ bossGroup.shutdownGracefully();
+ workerGroup.shutdownGracefully();
+ }
+ }
+
+
+}
diff --git a/entrance/pom.xml b/entrance/pom.xml
index 5b1e7b58..31d7f48d 100644
--- a/entrance/pom.xml
+++ b/entrance/pom.xml
@@ -26,6 +26,11 @@
user
1.0.0
+
+ com.njcn.gather
+ detection
+ 1.0.0
+
diff --git a/pom.xml b/pom.xml
index df54fd82..28534665 100644
--- a/pom.xml
+++ b/pom.xml
@@ -12,6 +12,7 @@
system
user
device
+ detection
pom
融合各工具的项目