通讯数据处理规则定义加字节数据处理

  • 大家好,我是你们的好朋友程序员:铭文
    • 一:需要交互数据格式的环境
    • 二:具体的定义模式:

大家好,我是你们的好朋友程序员:铭文

先简单说下具体的这篇文章我会详细的讲解下我们通信中数据为了防止粘包,分包,粘包的话存在的问题,解决思路
,和一些源码,需要所以源码的可以私聊我。我准备基于socket通信来讲,Socket通信这个不必再说了,不会的朋友
可以看我以前博客的地址:https://blog.csdn.net/weixin_44957831/article/details/106197901

一:需要交互数据格式的环境

我们上位机和下位机做数据的交互:
1.下位机提交数据 出现问题了,数据不完整了。怎么解决判断这个数据到底完整与否呢。这个时候就需要传输下这个数据的长度了。这个就是一个关键的点了。
2.下位机提交的数据:因为是单片机程序,提交的数据大小也会有问题,可以服务器上面开辟的缓存空间:[1024 * 1024 * 3] 很大了,接受没有问题,但是下位机提交的数据,受限制于框架和单片机程序的负载能力,数据提交的时候,很多情况下会出现分包的情况。先解决这个分包的情况:数据分包了绝对会有第一条数据第二条数据的情况吧。这个时候我们就要再次定义一个关键点,指针标识这条紧跟的数据是不是第一条数据。

二:具体的定义模式:

直接上干货,不墨迹直接上处理思路和处理模式,有不明白的地方可以给我留言,

1.我们的数据必须设计成包头加包体的模式。
比如:
包头:@@@@1234
包体:具体提交过来的数据Data;
包头里面我们要加一层业务:@@@@说明的是这个数据的开头。1234代表的是包体数据的字节长度。这样就可以很简单的来实现我们的分包操作了。
2.分包算法:基本思路就是:我们创建一个缓存来存放拼接的数据可以用字节数据来操作。结合并发字典(ConcurrentDictionary:key:来存放socket客户端的句柄,value:来存放当前客户端提交的数据就可以了)来实现。用的方法也是比较常用的具体的用法可以看看官方文档地址:
链接: ConcurrentDictionary官方文档详细解释.
写一个方法来处理我上面说的那些操作,可以用Buffer.BlockCopy方法来操作字节对象。
Buffer.BlockCopy用法(我摸索出来的,没找到文档):
Buffer.BlockCopy(操作的数据源,偏移量从第几个开始截取,剪切到的目标地方,开始的下坐标,结束的下坐标不包含这个坐标)
这样基本就可以实现分包合包等一系列的操作了。非常的简单希望可以帮到大家不明白的地方可以给我留言。
直接上代码了关键的地方我会加一些注释希望可以帮到大家。

下面展示一些 代码
调取方法:

//操作句柄和数据源结合。outputb就是分包的数据
OnReceive(token.Socket.Handle, outputb)
//包头长度 固定4
static int headSize = 4;
//定义并发字典
static ConcurrentDictionary<IntPtr, byte[]> dic = new ConcurrentDictionary<IntPtr, byte[]>();
//下面直接上方法 有注释的/// <summary>/// 接收客户端发来的数据/// </summary>/// <param name="connId">每个客户的会话ID</param>/// <param name="bytes">缓冲区数据</param>/// <returns></returns>public static string OnReceive(IntPtr connId, byte[] bytesin){//提交的用户内存数据byte[] surplusBuffer = null;int totalLen = 0;string DataLengStr = "";表头数据//byte[] Headerbyte = new byte[8];//前四条是否为第一条数据 就是$的过滤byte[] HeaderIn = new byte[4];//数据长度byte[] DataLeng = new byte[4];byte[] bytes;if (bytesin.Length > 4){bytes = new byte[bytesin.Length - 4];}else{bytes = new byte[bytesin.Length];}if (bytesin.Length > 8){byte[] DataSouLeng = new byte[bytesin.Length - 4];//Buffer.BlockCopy(bytesin, 0, Headerbyte, 0, 8);//从缓冲区里读取包头的字节Buffer.BlockCopy(bytesin, 0, HeaderIn, 0, 4);//从缓冲区里读取包头的字节Buffer.BlockCopy(bytesin, 4, DataLeng, 0, 4);//从缓冲区里读取包头的字节string HeaderInString = Encoding.Default.GetString(HeaderIn);DataLengStr = Encoding.Default.GetString(DataLeng);//如果是第一条数据if (HeaderInString == "@@@@"){byte[] xbtye = null;dic.TryRemove(connId, out xbtye);surplusBuffer = null; //设置空 回到原始状态totalLen = 0; //清0//重新拼接数据Buffer.BlockCopy(bytesin, 4, DataSouLeng, 0, bytesin.Length - 4);bytes = DataSouLeng;}else{bytes = bytesin;}}String strc = "";//bytes 为系统缓冲区数据//bytesRead为系统缓冲区长度int bytesRead = bytes.Length;if (bytesRead > 0){if (dic.TryGetValue(connId, out surplusBuffer)){byte[] curBuffer = surplusBuffer.Concat(bytes).ToArray();//拼接上一次剩余的包//更新会话ID 的最新字节dic.TryUpdate(connId, curBuffer, surplusBuffer);surplusBuffer = curBuffer;//同步}else{//添加会话ID的bytesdic.TryAdd(connId, bytes);surplusBuffer = bytes;//同步}//已经完成读取每个数据包长度int haveRead = 0;//这里totalLen的长度有可能大于缓冲区大小的(因为 这里的surplusBuffer 是系统缓冲区+不完整的数据包)totalLen = surplusBuffer.Length;while (haveRead <= totalLen){//如果在N此拆解后剩余的数据包连一个包头的长度都不够//说明是上次读取N个完整数据包后,剩下的最后一个非完整的数据包if (totalLen - haveRead < headSize){byte[] byteSub = new byte[totalLen - haveRead];//把剩下不够一个完整的数据包存起来Buffer.BlockCopy(surplusBuffer, haveRead, byteSub, 0, totalLen - haveRead);dic.TryUpdate(connId, byteSub, surplusBuffer);surplusBuffer = byteSub;totalLen = 0;break;}//如果够了一个完整包,则读取包头的数据byte[] headByte = new byte[headSize];Buffer.BlockCopy(surplusBuffer, haveRead, headByte, 0, headSize);//从缓冲区里读取包头的字节int bodySize = Convert.ToInt32(Encoding.Default.GetString(headByte));//从包头里面分析出包体的长度//BitConverter.GetBytes();//byte[] headByte3 = StringToByte("11");//这里的 haveRead=等于N个数据包的长度 从0开始;0,1,2,3....N//如果自定义缓冲区拆解N个包后的长度 大于 总长度,说最后一段数据不够一个完整的包了,拆出来保存if (haveRead + headSize + bodySize > totalLen){byte[] byteSub = new byte[totalLen - haveRead];Buffer.BlockCopy(surplusBuffer, haveRead, byteSub, 0, totalLen - haveRead);dic.TryUpdate(connId, byteSub, surplusBuffer);surplusBuffer = byteSub;break;}else{//挨个分解每个包,解析成实际文字//Encoding.Default.GetString,UTF8strc = Encoding.Default.GetString(surplusBuffer, haveRead + headSize, bodySize);//strc = (string.Format(" > {0}[OnReceive] -> {1}", connId, strc));//依次累加当前的数据包的长度haveRead = haveRead + headSize + bodySize;//如果当前接收的数据包长度正好等于缓冲区长度,则待拼接的不规则数据长度归0if (headSize + bodySize == surplusBuffer.Length){byte[] xbtye = null;dic.TryRemove(connId, out xbtye);surplusBuffer = null;//设置空 回到原始状态totalLen = 0;//清0}}}}return strc;}

上面就是实现了数据的分包粘包等操作。操作的也是原始的字节数据。
调取的话就非常简单了。直接传输数据源和socket指针便可。
调取方法:

//操作句柄和数据源结合
OnReceive(token.Socket.Handle, outputb)

通讯数据处理规则定义加字节数据处理相关推荐

  1. Dreamweaver CSs网页设计css规则定义翻译

    在Dreamweaver CS网页设计中,对于初学者来说,学习CSS样式基础其实不是很难,现在小编将CSS规则定义翻译如下,希望能给一起学习网页设计的网友更多方便,可供参考与理解. 当然,如果你觉得此 ...

  2. css txt-aline,CSS规则定义.doc

    CSS规则定义 CSS规则定义 一.类型 Font-family:字体 font-size:字体大小: xx-small 最小 x-small 较小 small 小 medium 正常(默认值) la ...

  3. apache的rewrite规则无法加载问题

    apache的rewrite规则无法加载问题. <VirtualHost *:80> ServerAdmin k@5.com DocumentRoot /data/web/xxx Serv ...

  4. api 规则定义_API有规则,而且功能强大

    api 规则定义 Disclaimer: I am an independent researcher @Taraaz with no affiliation with any of the comp ...

  5. 开源通用爬虫框架YayCrawler-页面的抽取规则定义

    本节我将向大家介绍一下YayCrawler的核心-页面的抽取规则定义,这也是YayCrawler能够做到通用的主要原因之一.如果我要爬去不同的网站的数据,尽管他们的网站采用的开发技术不同.页面的结构不 ...

  6. 《Cisco防火墙》一8.7 通过NAT规则定义连接限制

    本节书摘来自异步社区<Cisco防火墙>一书中的第8章,第8.7节,作者 [巴西]Alexandre M.S.P. Moraes,更多章节内容可以访问云栖社区"异步社区" ...

  7. 《游戏机制——高级游戏设计技术》一1.1 规则定义游戏

    本节书摘来异步社区<游戏机制--高级游戏设计技术>一书中的第1章,第1.1节,作者: [美]Ernest Adams 译者: 石曦 责编: 陈冀康,更多章节内容可以访问云栖社区" ...

  8. css规则定义的分类,.css规则定义

    文本样式的定义 定义文本样式.保存CSS规则后系统将行动打开"CSS规则定义"对话框. [字体]:选择所需要的字体. [大小]:定义字体大小. [样式]:可选择字体的特殊样式,即& ...

  9. css规则定义的分类,CSS规则定义英汉对照表

    <CSS规则定义英汉对照表>由会员分享,可在线阅读,更多相关<CSS规则定义英汉对照表(4页珍藏版)>请在人人文库网上搜索. 1.CSS规则定义英汉对照表一.类型font-fa ...

最新文章

  1. 转、转、转——陀螺的梦话
  2. seaborn可视化绘制双变量分组条形图(Annotating Grouped Barplot: Side-by-side)、添加数值标签进行标记
  3. jQuery判断checkbox是否选中
  4. 算法运行时间中的对数
  5. 一些dos下简单命令
  6. python 路由转发_[转载]无线传感器网络路由协议(转)
  7. 前端 new实例后销毁实例_后浇带怎么做不漏浆?看个实例
  8. patterns practices: Mobile Architecture Pocket Guide
  9. html5 梵高 星,上海梵高星空艺术馆门票
  10. Mongodb极简实践
  11. 提高情商,从这几方面做
  12. 台式计算机如何定时关机,台式电脑如何设置每天定时关机
  13. 为什么说采购一定要成为专家
  14. 2021cka考试标准答案
  15. STM32F103ZE和STM32F207ZG的芯片区别
  16. bim综合建模插件 进行碰撞检查只需六步!
  17. linux系统微内核,微内核操作系统的定义及用微内核设计的系统,附Linux是单内核结构介绍...
  18. 利用Civil3d导入桥梁中线至Revit中建立桥梁上部结构
  19. 补缴2个月社保折腾1年多 刁钻政策玩死人
  20. 快速传输大文件,怎么通过网络传大文件给对方(1G以上)

热门文章

  1. 香港海关去年执法案件逾2.2万宗 2万人被捕
  2. 电脑技巧:Windows微信3.9.5更新一览
  3. ACM教程 - 强连通分量(Tarjan)
  4. 最详细的Neo4J解读(附安装教程)
  5. 弹弹弹——弹走队列2
  6. MQTT协议与EMQ
  7. 产品经理和程序员之间的硝烟
  8. 名帖215 赵孟頫 行书《楞严经》
  9. KITTI数据集百度云下载
  10. 启明星辰调整回购方案:回购价由不超过20元调整为不超过30元