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

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

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

先简单说下具体的这篇文章我会详细的讲解下我们通信中数据为了防止粘包,分包,粘包的话存在的问题,解决思路
,和一些源码,需要所以源码的可以私聊我。我准备基于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. 通信专业考研考C语言,2016年北京邮电大学信息与通信工程学院C语言程序设计考研复试题库...
  2. 输出超限怎么解决 oj_三菱PLC输出指示灯输出模块不亮怎么解决
  3. 02 docker的基本用法
  4. 老司机带你重构Android的v4包的部分源码
  5. java 方法 示例_Java扫描仪具有示例的NextNextInt()方法
  6. python自定义函数的参数调用_python | 自定义函数
  7. 总结一下java并发包的学习
  8. 徐培成2017大数据Hadoop经典案例-徐培成-专题视频课程
  9. WPS文字无法创建对象,请确认对象已在系统注册表注册的问题
  10. python中输入多个值用什么符号隔开_字典中多个元素之间使用
  11. 解决报错:info There appears to be trouble with your network connection. Retrying...
  12. 快捷方式图标 html,界面上的应用程序快捷方式图标都变成了IE图标
  13. 从轻盈奶茶到拉普山鲜奶茶,罗曼林实现品类突围
  14. Word控件Spire.Doc 【文本】教程(14) ;如何用图片替换Word中的文字
  15. java实现手机短信发送的功能详细代码
  16. 学习ARM开发(1)
  17. ffmpeg4.4项目学习--H264编码之码率控制模式及参数配置
  18. 初学python体验
  19. 系统错误:下列引导或系统启动驱动程序无法加载: HWiNFO32
  20. 经度、纬度、高度转换成大地坐标系XYZ的程序

热门文章

  1. 如何从ST官网获得标准库文件?
  2. JUnit4和JUnit5的主要区别
  3. 第1天 | 3天搞定Pyecharts数据分析,语法篇
  4. 神舟1999元本上市
  5. 华硕uefi不识别linux安装u盘启动,uefi无法从u盘启动系统
  6. 重磅来袭!这么香的技术还不快点学起来,含BATJM大厂
  7. 深圳特区建立40周年,说说我对深圳的十年印象
  8. nodejs顶层路由设计
  9. 一元线性回归方程第二部分——一元线性回归模型
  10. java高级:Scanner和String类介绍