当前位置: 首页 > news >正文

工业数采引擎-通信链路SOCKET

通信库:DotNetty

封装实现:TcpServer、TcpClient、Udp

TCP协议特性:面向连接协议;每个新连接都会创建独立的ChannelHandler实例;TcpHandler构造函数在每次客户端连接时触发
UDP协议特性:无连接协议;整个服务端只创建单例UdpHandler;所有UDP数据包共享同一个处理器实例;UdpHandler构造函数仅在服务启动时触发一次

Server
1. 端口复用
2. 定时清理链路

TcpClient
1. 指定本地ip及端口
2. 自动重连

其他
1. 上线,离线,数据接收消息通知
2. 接收缓冲数据存储

复制代码

using DotNetty.Buffers;
using FusionDrive.DotNetty.Util;
using FusionDrive.DotNetty.Util.decode;
using FusionDrive.DotNetty.Util.socket;
using System.Net;
using System.Text;namespace FusionDrive.DotNetty
{internal class Program{static void Main(string[] args){//Test_Server();Test_Client();Console.ReadLine();}static void Test_Server(){OHMDecode ohm = new OHMDecode();PipeManager.CheckLink();var server = new CommunicationServer();//server.Listen(8801);server.Listen(8801, isTcp: true, isUdp: true, udpTargetEndPoint: new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8802));server.OnPipeOnline += async (session) =>{Logger.Info($"-> {session.RemoteAddress?.ToString()} 上线"); };server.OnPipeOffline += async (session) =>{Logger.Info($"<- {session.RemoteAddress?.ToString()} 离线");};server.OnPipeReceived += async (session, buffer) =>{// dtu模式if (session.IsFirstConnect){// 心跳包session.IsFirstConnect = false;var sessionId = Encoding.UTF8.GetString(buffer);session.UpdateSessionId(sessionId);// 下发TCP指令SendData(session.SessionId);// 清理PipeManager.ClearByteBuffer(sessionId);}else{ohm.ProtocolFormat(session.SessionId, session.ByteBuffer);}// 下发UDP指令SendData(session.SessionId, session.TargetEndPoint);SendData(session.SessionId, session.RemoteAddress);};}static void Test_Client(){AirDecode air = new AirDecode();var tcpClient = new TcpClient();tcpClient.Connect("127.0.0.1", 8801, autoConect:true);tcpClient.OnPipeOnline += async (session) =>{Logger.Info($"-> {session.RemoteAddress?.ToString()} 上线");};tcpClient.OnPipeOffline += async (session) =>{Logger.Info($"<- {session.RemoteAddress?.ToString()} 离线");};tcpClient.OnPipeReceived += async (session, buffer) =>{air.ProtocolFormat(session.SessionId, session.ByteBuffer);////tcpClient.DisConnect();};}static void SendData(string sessionId, EndPoint endPoint = null){IByteBuffer message = Unpooled.Buffer();message.WriteString("*TRG\r\n", Encoding.UTF8);var p = PipeManager.CheckSession(sessionId, out string errmsg);p.Send(message, endPoint);} }
}

复制代码

复制代码

using DotNetty.Buffers;
using System.Text;namespace FusionDrive.DotNetty.Util.decode
{public class AirDecode : NettyDecode{const byte HEAD = 02;public override void ProtocolFormat(string sessionId, IByteBuffer oldBuffer){ try{if (IsHeadLost(oldBuffer, 1)) return ;// 掉包bool headok = false;// 垃圾包处理oldBuffer.MarkReaderIndex();while (oldBuffer.IsReadable()){byte head1 = oldBuffer.ReadByte();// 1字节:标识头if (HEAD == head1){headok = true;break;}else{oldBuffer.MarkReaderIndex();}}if (!oldBuffer.IsReadable()){if (!headok) return ; // 垃圾包}// 3字节:ascii长度if (IsBagLost(oldBuffer, 3)) return ;// 掉包byte[] arrlen = new byte[3]; oldBuffer.ReadBytes(arrlen);int len = Convert.ToInt32(Encoding.ASCII.GetString(arrlen));// n字节:数据包len = len + 2;// 包含结束帧及校验位if (IsBagLost(oldBuffer, len)) return ;// 掉包byte[] data = new byte[len]; oldBuffer.ReadBytes(data);Logger.Info($"AirDecode sessionId:{sessionId},data:{Common.ToHexString(data, data.Length, true)}");// 压力值string pressureValue = "999";var pressureFlg = Encoding.ASCII.GetString(new byte[] { data[55] });var pressureNumber = Encoding.ASCII.GetString(new byte[] {data[56], data[57], data[58], data[59], data[60],data[61], data[62], data[63], data[64], data[65] });// 可能为----------- if (double.TryParse(pressureNumber, out double result1)){pressureNumber = result1.ToString();pressureValue = pressureFlg + pressureNumber;}Logger.Info($"AirDecode 压力值:{pressureValue}");if (oldBuffer.IsReadable()){ProtocolFormat(sessionId, oldBuffer);// 处理粘包}else{oldBuffer.Clear();// 包完整,清理} }catch (Exception ex){Logger.Error($"AirDecode 协议解析错误,sessionId:{sessionId}:{ex.Message}");} }}
}

复制代码

image

http://www.dtcms.com/a/316793.html

相关文章:

  • Python高级编程与实践:Python网络编程基础与实践
  • Linux的NFS与Autofs配置指南
  • mac安装pycharm
  • 2048小游戏
  • VUE2 学习笔记 合集
  • 如何在nuxt项目中使用axios进行网络请求?
  • 【STM32】HAL库中的实现(三):PWM(脉冲宽度调制)
  • C语言线程同步详解(互斥锁、信号量、条件变量和读写锁)
  • GPU 安装
  • 前端包管理器深度对比
  • 双模对讲机是什么意思?与模拟/数字对讲机有什么区别?
  • 使用 ECharts 实现小区住户数量统计柱状图
  • Leetcode-2080区间内查询数字的频率
  • Spring AI 系列之三十六 - Spring AI Alibaba-nl2sql
  • 02--类和对象
  • 大厂面试题
  • React在使用create-react-app创建项目慢的解决办法
  • TanStack React Query 完全指南:从0到精通
  • Flux.1系列模型解析--Flux.1 Tools
  • 【模电笔记】—— 直流稳压电源——整流、滤波电路
  • 无线网络扫描工具 ‌WifiInfoView‌
  • 高通平台Wi-Fi Display学习-- 调试 Wi-Fi Display 问题
  • 人工智能领域、图欧科技、IMYAI智能助手2024年全年历史更新大事件汇总
  • 人工智能领域、图欧科技、IMYAI智能助手2025年6月更新月报
  • RHCA05--进程管理与文件系统管理
  • 基于SpringBoot的青少年网络安全教育系统
  • C语言:20250805学习(文件预处理)
  • 系统集成项目管理工程师【第十一章 规划过程组】项目管理计划、范围管理与收集需求篇
  • VUE丢失long类型精度,使用 json-bigint 库解析大整数
  • 基于腾讯iOA的企业安全防护体系融合升级指南:从边界防御到无边界纵深防护