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 融合各工具的项目