物联网通讯协议 iot-modbus V3.2.8 发布
编辑切换为居中
添加图片注释,不超过 140 字(可选)
编辑切换为居中
添加图片注释,不超过 140 字(可选)
编辑切换为居中
添加图片注释,不超过 140 字(可选)
编辑切换为居中
添加图片注释,不超过 140 字(可选)
编辑切换为居中
添加图片注释,不超过 140 字(可选)
package com.takeoff.iot.modbus.server.connect; import com.takeoff.iot.modbus.common.entity.ChannelConnectData; import com.takeoff.iot.modbus.common.enums.DeviceConnectEnum; import com.takeoff.iot.modbus.common.utils.CacheUtils; import com.takeoff.iot.modbus.common.utils.JudgeEmptyUtils; import com.takeoff.iot.modbus.common.utils.SpringContextUtil; import com.takeoff.iot.modbus.netty.channel.MiiChannel; import com.takeoff.iot.modbus.netty.device.MiiDeviceChannel; import io.netty.bootstrap.Bootstrap; import io.netty.channel.*; import io.netty.channel.ChannelHandler.Sharable; import lombok.extern.slf4j.Slf4j; import org.springframework.context.ApplicationContext; import org.springframework.util.ObjectUtils; import java.net.SocketAddress; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; /** * 类功能说明:客户端链接管理器<br/> * 公司名称:TF(腾飞)开源 <br/> * 作者:luorongxi <br/> */ @Slf4j @Sharable public class MiiServerConnect extends ChannelInboundHandlerAdapter { private ApplicationContext getApplicationContext = SpringContextUtil.applicationContext; private static int TIMEOUT = 5000; /** * 连接成功次数 */ private Map<String, Integer> onLineMap = new HashMap<>(); /** * 连接断开次数 */ private Map<String, Integer> breakOffMap = new HashMap<>(); public MiiServerConnect(){ } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { //成功后,重连失败次数清零 Channel channel = ctx.channel(); ctx.fireChannelActive(); if(!JudgeEmptyUtils.isEmpty(channel.remoteAddress())){ String address = channel.remoteAddress().toString().substring(1,channel.remoteAddress().toString().length()); MiiChannel miiChannel = new MiiDeviceChannel(channel); Integer onLine = (ObjectUtils.isEmpty(onLineMap.get(miiChannel.name())) ? 0 : onLineMap.get(miiChannel.name())) + 1; onLineMap.put(miiChannel.name(), onLine); ChannelConnectData connectServerData = new ChannelConnectData(this, DeviceConnectEnum.ON_LINE.getKey(), address, onLine); if(!JudgeEmptyUtils.isEmpty(connectServerData) && !JudgeEmptyUtils.isEmpty(getApplicationContext)){ getApplicationContext.publishEvent(connectServerData); //将柜地址与通讯管道的绑定关系写入缓存 CacheUtils.put(miiChannel.name(), miiChannel); } } } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { ctx.fireChannelInactive(); Channel channel = ctx.channel(); if(!JudgeEmptyUtils.isEmpty(channel) && !JudgeEmptyUtils.isEmpty(channel.remoteAddress())){ String address = channel.remoteAddress().toString().substring(1,channel.remoteAddress().toString().length()); MiiChannel miiChannel = new MiiDeviceChannel(channel); Integer breakOff = (ObjectUtils.isEmpty(breakOffMap.get(miiChannel.name())) ? 0 : breakOffMap.get(miiChannel.name())) + 1; breakOffMap.put(miiChannel.name(), breakOff); ChannelConnectData connectServerData = new ChannelConnectData(this, DeviceConnectEnum.BREAK_OFF.getKey(), address, breakOff); if(!JudgeEmptyUtils.isEmpty(connectServerData) && !JudgeEmptyUtils.isEmpty(getApplicationContext)){ getApplicationContext.publishEvent(connectServerData); } //将通讯管道的绑定关系从缓存中删除 CacheUtils.remove(miiChannel.name()); //连接断开后的最后处理 ctx.pipeline().remove(ctx.handler()); ctx.deregister(); ctx.close(); } } }
package com.takeoff.iot.modbus.common.entity; import com.takeoff.iot.modbus.common.enums.DeviceConnectEnum; import com.takeoff.iot.modbus.common.utils.JudgeEmptyUtils; import org.springframework.context.ApplicationEvent; import lombok.Getter; @Getter public class ChannelConnectData extends ApplicationEvent { /** * 描述: TODO <br/> * Fields serialVersionUID : TODO <br/> */ private static final long serialVersionUID = 2111432846029949421L; private String deviceAddress = null; private Integer deviceConnect = null; private String connectMsg = null; public ChannelConnectData(Object source, Integer deviceConnect, String deviceAddress, int count) { super(source); if(!JudgeEmptyUtils.isEmpty(deviceAddress)){ this.deviceConnect = deviceConnect; this.deviceAddress = deviceAddress; this.connectMsg = "设备:"+ deviceAddress + DeviceConnectEnum.getName(deviceConnect) + ",累计:"+ count + "次"; } } }
package com.takeoff.iot.modbus.test.listener; import com.takeoff.iot.modbus.common.entity.ChannelConnectData; import com.takeoff.iot.modbus.common.utils.JudgeEmptyUtils; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; import lombok.extern.slf4j.Slf4j; @Slf4j @Component public class ChannelConnectListener { @EventListener public void handleReceiveDataEvent(ChannelConnectData data) { if(JudgeEmptyUtils.isEmpty(data.getDeviceConnect())){ log.info("设备连接状态码:"+data.getDeviceConnect()+" ---> "+data.getConnectMsg()); } } }
package com.takeoff.iot.modbus.server; import java.util.List; import java.util.concurrent.TimeUnit; import com.takeoff.iot.modbus.common.utils.CacheUtils; import com.takeoff.iot.modbus.netty.device.MiiDeviceChannel; import com.takeoff.iot.modbus.netty.device.MiiDeviceGroup; import com.takeoff.iot.modbus.netty.device.MiiControlCentre; import com.takeoff.iot.modbus.common.bytes.factory.MiiDataFactory; import com.takeoff.iot.modbus.common.data.MiiHeartBeatData; import com.takeoff.iot.modbus.common.message.MiiMessage; import com.takeoff.iot.modbus.netty.channel.MiiChannel; import com.takeoff.iot.modbus.netty.channel.MiiChannelGroup; import com.takeoff.iot.modbus.netty.data.factory.MiiServerDataFactory; import com.takeoff.iot.modbus.netty.handle.*; import com.takeoff.iot.modbus.netty.listener.MiiListener; import com.takeoff.iot.modbus.server.connect.MiiServerConnect; import com.takeoff.iot.modbus.server.message.sender.MiiServerMessageSender; import com.takeoff.iot.modbus.server.message.sender.ServerMessageSender; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; import io.netty.handler.timeout.IdleStateEvent; import io.netty.handler.timeout.IdleStateHandler; import lombok.Getter; import lombok.extern.slf4j.Slf4j; /** * 类功能说明:设备通讯服务端<br/> * 公司名称:TF(腾飞)开源 <br/> * 作者:luorongxi <br/> */ @Slf4j public class MiiServer extends ChannelInitializer<SocketChannel> implements MiiControlCentre { private static int IDLE_TIMEOUT = 60000; private EventLoopGroup bossGroup; private EventLoopGroup workerGroup; private ChannelFuture future; private int port,nThread; @Getter private MiiChannelGroup groups; private MiiServerConnect connect; private ServerMessageSender sender; private MiiListenerHandler handler; private MiiDataFactory dataFactory; /** * 创建指定服务端口,默认线程数的服务端 * @param port 服务端口 */ public MiiServer(int port){ this(port, 0, IDLE_TIMEOUT); } /** * 创建指定服务端口,指定线程数的服务端 * @param port 服务端口 * @param nThread 执行线程池线程数 * @param heartBeatTime 心跳检测超时时间(单位:毫秒) */ public MiiServer(int port, int nThread, int heartBeatTime){ this.port = port; this.nThread = nThread; this.IDLE_TIMEOUT = heartBeatTime; this.groups = new MiiChannelGroup(); this.connect = new MiiServerConnect(); this.sender = new MiiServerMessageSender(); this.handler = new MiiListenerHandler(this.groups); this.handler.addListener(MiiMessage.HEARTBEAT, new MiiListener() { @Override public void receive(MiiChannel channel, MiiMessage message) { //通讯通道绑定设备IP groups.get(channel.name()).name(message.deviceGroup()); log.info("Netty通讯已绑定设备IP:"+ message.deviceGroup()); } }); this.dataFactory = new MiiServerDataFactory(); } /** * 启动服务 */ public void start(){ bossGroup = new NioEventLoopGroup(1); workerGroup = new NioEventLoopGroup(nThread); ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .handler(new LoggingHandler(LogLevel.INFO)) .childHandler(this); future = b.bind(port); } /** * 停止服务 */ public void stop(){ future.channel().closeFuture(); workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } /** * 根据名称/地址找已连接设备组 * 名称/地址不存在或者未连接时返回null值 * @param name 名称/地址 * @return 设备组 */ public MiiChannel group(String name) { return get(name); } /** * 列出所有已连接设备组清单 * @return 所有已连接身边组清单 */ public List<MiiChannel> groups() { return groups.list(); } public ServerMessageSender sender(){ return sender; } /** * 添加接收指定指令的消息监听器 * @param command 指令类型 {@link MiiMessage} * @param listener 消息监听器 * @return 上一个消息监听器,如果没有返回null */ public MiiListener addListener(int command, MiiListener listener){ return handler.addListener(command, listener); } /** * 移除接收指定指令的消息监听器 * @param command 指令类型 {@link MiiMessage} * @return 移除消息监听器,如果没有返回null */ public MiiListener removeListener(int command){ return handler.removeListener(command); } @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline p = ch.pipeline(); MiiDeviceGroup group = new MiiDeviceChannel(ch); add(group); //服务端心跳检测超时时间,超时则主动断开链接 p.addLast(new IdleStateHandler(0, 0, IDLE_TIMEOUT, TimeUnit.MILLISECONDS)); p.addLast(new ChannelInboundHandlerAdapter(){ @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if(evt instanceof IdleStateEvent){ ctx.disconnect(); } else { super.userEventTriggered(ctx, evt); } } }); p.addLast(new MiiMessageEncoder()); p.addLast(new MiiBasedFrameDecoder()); p.addLast(new MiiMessageDecoder(dataFactory)); p.addLast(connect); p.addLast(handler); p.addLast(new MiiExceptionHandler()); } @Override public boolean add(MiiChannel channel) { return groups.add(channel); } @Override public MiiChannel remove(String name) { return groups.remove(name); } @Override public MiiChannel get(String name) { return groups.get(name); } }

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
trzsz.js 发布 1.0 正式版,支持在浏览器中使用 rz / sz
trzsz.js 发布 1.0 正式版,优化了对 Windows 的支持,优化了速度。 trzsz(trz /tsz) 是一个兼容 tmux 的文件传输工具,和 lrzsz ( rz /sz ) 类似,并且有进度条,支持目录传输,支持拖动上传。 https://github.com/trzsz/trzsz.js支持在 web 浏览器中使用类似 rz /sz 上传和下载文件,也支持 electron 开发的跨平台应用。 js版的trzsz.js,可以在 Chrome浏览器中使用trzsz( trz / tsz ) 上传和下载文件,如图: js版的trzsz.js,可以集成到 electron 开发的终端中,使用trzsz( trz / tsz ) 上传和下载文件,如图:
- 下一篇
Alist <3.5.1 存在文件上传漏洞
漏洞描述 Alist 是一个支持多存储的文件列表程序。 Alist 3.5.1之前版本中由于 handles 模块缺少对上传文件用户的身份验证,具有文件上传权限的攻击者可通过修改上传文件路径将任意文件上传至任意目录,包括具有密码限制的目录。 漏洞名称 Alist <3.5.1 存在文件上传漏洞 漏洞类型 认证机制不恰当 发现时间 2022-12-13 漏洞影响广度 一般 MPS编号 MPS-2022-65333 CVE编号 CVE-2022-45968 CNVD编号 - 影响范围 github.com/alist-org/alist/v3@[3.0.0-beta.0, 3.5.1) 修复方案 升级github.com/alist-org/alist/v3到 3.5.1 或更高版本 参考链接 https://www.oscs1024.com/hd/MPS-2022-65333 https://nvd.nist.gov/vuln/detail/CVE-2022-45968 https://github.com/alist-org/alist/issues/2444 https://g...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7,CentOS8安装Elasticsearch6.8.6
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS7安装Docker,走上虚拟化容器引擎之路
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Red5直播服务器,属于Java语言的直播服务器
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果