工业数采引擎-通信链路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.pswp.cn/web/92350.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/92350.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PHP小白零基础入门(附视频教程)

概述 PHP是一种通用开源脚本语言&#xff0c;常用于服务器端Web开发&#xff0c;具有语法简单、上手快等特点。视频教程&#xff1a;https://pan.quark.cn/s/8f214c23301b 搭建开发环境&#xff1a; 选择集成工具&#xff1a;可选择XAMPP&#xff08;支持Windows/Mac/Linux…

验证码等待时间技术在酒店自助入住、美容自助与社区场景中的应用必要性研究—仙盟创梦IDE

代码 代码 完整<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>验证码倒计时</title><s…

Flask从入门到实战:基础、进阶、项目架构与接口测试

本文将带你从零开始掌握Flask框架&#xff0c;涵盖基础使用、进阶技巧、项目架构设计&#xff0c;并提供完整的接口测试客户端代码。 目录一、Flask基础入门1.1 Flask简介与安装1.2 第一个Flask应用1.3 路由与请求处理1.4 请求与响应处理二、Flask进阶使用2.1 模板引擎Jinja22.…

华为云产品图解

框架图核心说明: 1. 分层逻辑清晰 基础设施层(IaaS):提供最基础的计算(ECS/BMS)、存储(OBS/EVS)、网络(VPC/CDN)资源,是所有上层服务的 “物理底座”。 平台服务层(PaaS):基于 IaaS 构建,提供容器编排(CCE)、数据库(GaussDB)、大数据与 AI(ModelArts)、中…

Git 中如何回退到以前的提交记录?

回答重点要在 Git 中回退到以前的提交记录&#xff0c;你可以使用 git reset 命令。这个命令有三个常用选项来控制你想要回退的程度&#xff1a;1&#xff09; git reset --soft <commit> &#xff1a;仅修改 HEAD 指针&#xff0c;不修改索引和工作区内容。2&#xff09…

JavaWeb03——基础标签及样式(表单)(黑马视频笔记)

1.表单标签 及 表单属性表单标签是 &#xff1a;<form> 表单属性有&#xff1a;action 和 method&#xff1b;action属性&#xff1a;规定向何处发送表单数据。method属性&#xff1a;规定用什么方法发送数据。&#xff08;get和post&#xff09;get:在发送的url后面拼接…

STM32的SPI通信(软件读写W25Q64)

在了解完I2C通信后&#xff0c;不免会接触到到SPI通信。而一开始&#xff0c;可能会觉得两者好似没什么区别。为什么要学SPI呢&#xff0c;I2C和SPI有什么区别呢。为此我详细展开说说。1.什么是 SPI&#xff1f;SPI&#xff0c;全称 Serial Peripheral Interface&#xff0c;中…

子词分词器(Byte Pair Encoding + WordPiece)

参考文章&#xff1a;子词分词器BPE和WordPiece理解_wordpeice-CSDN博客 子词分词器BPE和WordPiece理解_wordpeice-CSDN博客 WordPiece 和 BPE 的区别-CSDN博客 点互信息&#xff08;PMI&#xff09;和正点互信息&#xff08;PPMI&#xff09;-CSDN博客 https://zhuanlan.z…

阿里招AI产品运营

AI产品运营&#xff08;岗位信息已经过jobleap.cn授权&#xff0c;可在csdn发布&#xff09;灵犀互娱 广州收录时间&#xff1a; 2025年08月05日职位描述负责AI技术在游戏行业的应用与落地&#xff0c;专注于海外市场的运营中台建设&#xff1b; 将结合AI技术与游戏行业特点&a…

Git 分支迁移完整指南(结合分支图分析)

基于分支图的当前状态分析 分支图关键信息解读​分支结构​&#xff1a; #mermaid-svg-gc9SPnwlbrM2FzHf {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-gc9SPnwlbrM2FzHf .error-icon{fill:#552222;}#mermaid-svg-…

小程序省市级联组件使用

背景。uni-data-picker组件用起来不方便。调整后级联效果欠佳&#xff0c;会关闭弹窗需要重新选择。解决方案。让cursor使用uniapp 原生组件生成懒加载省市级联 <template><view class"picker-cascader"><view class"cascader-label">&l…

Java技术栈/面试题合集(8)-Redis篇

场景 Java入门、进阶、强化、扩展、知识体系完善等知识点学习、性能优化、源码分析专栏分享: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/140870227 通过对面试题进行系统的复习可以对Java体系的知识点进行查漏补缺。 注: 博客: 霸道流氓气质-CSDN博…

川翔云电脑:引领开启算力无边界时代

一、何为云电脑&#xff1f;重新定义“主机”概念 云电脑将传统本地计算机的核心硬件资源&#xff08;CPU、GPU、内存、硬盘等&#xff09;集中部署于远程高性能数据中心&#xff0c;通过网络技术将虚拟桌面实时传输到您的任意访问设备上。 ​​如同将高配主机装入云端&#…

tc 介绍

目录 1.背景 2. tc介绍 3. tc 丢包 1.背景 需要使用tc 构造丢包场景&#xff0c;注意tc 丢包不能确定丢弃的是否是payload 数据包&#xff0c;有可能丢弃 ack 包。 2. tc介绍 1. 无法正常使用 [rootpool-100-1-1-18 /]# [rootpool-100-1-1-18 /]# tc qdisc add dev swif…

LabVIEW注册表操作

​本文围绕LabVIEW中操作Windows 注册表的 4 个 VI 展开&#xff0c;介绍其功能、使用场景等并对比&#xff0c;助力工程师高效运用注册表交互功能。各 VI 功能说明&#xff08;一&#xff09;Write the Key功能&#xff1a;创建新注册表键&#xff0c;设置其值&#xff0c;随后…

阿里云部署若依后,浏览器能正常访问,但是apifox和小程序访问后报错链接被重置

项目场景&#xff1a;阿里云部署若依后浏览器能正常通过https访问,但是在apifox和小程序调用接口的时候生报错E问题描述apifox报错&#xff1a;curl报错&#xff1a;通过curl可以清楚的看到通过域名是能准确的访问到IP地址的&#xff0c;说明这个DNS是没有问题的&#xff0c;但…

升级 Elasticsearch 到新的 AWS Java SDK

作者&#xff1a;来自 Elastic David Turner, Dianna Hohensee Elasticsearch 使用官方的 AWS Java SDK 集成了某些 Amazon Web Services (AWS) 功能。这些集成最早在近 10 年前发布的 Elasticsearch 2.0 版本中引入。 最近&#xff0c;AWS 宣布 Elasticsearch 过去十年使用的…

从0到1学习微服务项目黑马头条day01-《APP端登录功能实现》

个人主页&#xff1a;VON文章所属专栏&#xff1a;黑马头条个人唯一微信&#xff1a;微信 有一起学习微服务的小伙伴可以加作者微信&#xff1a;单击即可添加 目录 一、前言 二、项目概述 1、技术栈 2、项目引入 三、改造项目 1、创建heima-leadnews-user 2、创建实体…

Renesas Electronics RZ/V2N 评估套件

简介Renesas Electronics RZ/V2N评估套件采用RZ/V2N中档嵌入式AI微处理器 (MPU) 为嵌入式人工智能 (AI) 应用提供全面的开发平台。该评估套件包括两块板&#xff1a;主板 (RTK0EF0186C02000BJ)&#xff0c;紧凑的153mm x 100mm外形尺寸和RTK0EF0168B00000BJ扩展板。其核心是RZ/…

使用PHP与Apache实现服务器端文件管理

引言 作为前端开发者&#xff0c;你可能经常需要与服务器文件系统交互。本文将详细介绍如何通过PHP配合Apache实现服务器端文件管理功能。即使你没有任何PHP经验&#xff0c;也能按照本教程实现完整解决方案&#xff01; 系统准备 PHP下载与安装 访问PHP官网下载页面 选择与…