什么是粘包、半包问题:

        粘包:例如服务端依次将两条消息发送给客户端,我们暂且简单的将这两条消息举例为"Hello"、"Unity",而客户端一次性读取到的内容却是"HelloUnity",像这种一次性读取到两条消息中数据内容的情况称之为粘包。

半包:例如服务端发送消息"Hello"给客户端,而客户端依次读取到"Hel","lo"两条消息,这种情况称之为半包。

粘包、半包发生的原因:

        粘包:消息发送方发送完完整的消息后,接收方没有及时处理(比如网络开小差,未能及时读取消息),数据滞留于缓冲区,此时发送方又继续发送了其他消息,那么接收方下次在缓冲区读取时,一次性读取到大于一条消息数据造成粘包。

半包:发送方发送消息数据大小为512字节,而接收方缓冲区剩余已不足512字节,造成半包。

究其根本原因,TCP为流式协议,消息不存在边界。

解决方案:

        1.固定长度法:服务端和客户端规定固定长度的缓冲区,当消息数据长度不足时,使用规定的填充字符进行填充。弊端:增加了不必要的数据传输,造成网络传输负担,不建议使用。

        2.结束标识法:在包体尾部增加标识符表示一条完整的消息数据已经结束。弊端:若消息体本身包含该标识符需要做转义处理,因此效率依然不高。

 3.长度信息法:将包体分为消息头+消息体,消息头中信息为消息体的长度,接收方通过该长度信息读取后面指定长度的内容,需要注意的是需限制可能的最大长度从而规定长度占用字节数。该方法为处理粘包半包问题的常用方法。核心代码:

发送端:

//将发送的内容转化为字节数据
byte[] bytes = Encoding.Default.GetBytes(content);
//消息体长度
Int16 length = (Int16)bytes.Length;
//消息头长度
byte[] lengthBytes = BitConverter.GetBytes(length);
//发送的包体 = 消息头 + 消息体
byte[] sendBytes = lengthBytes.Concat(bytes).ToArray();
//发送
socket.Send(sendBytes);

接收端:

//接收数据缓冲区
byte[] readBuffer = new byte[1024];
//接收缓冲区的数据长度
int bufferCount = 0;

bufferCount用于记录缓冲区中的有效数据长度,BeginReceive从缓冲区bufferCount的位置开始写入,缓冲区长度为1024,那么可写入的剩余量为1024 - bufferCount

socket.BeginReceive(readBuffer,             //接收缓冲区bufferCount,            //开始位置1024 - bufferCount,     //最多读取的数据长度0,                      //标志位ReceiveCallback,        //接收数据回调函数socket);

在收到新数据后,需要在回调函数中更新bufferCount,以便在下次接收数据时,写入到缓冲区中有效数据的后面。

Socket socket = (Socket)ar.AsyncState;
//接收数据的长度
int count = socket.EndReceive(ar);
bufferCount += count;

因为使用了Int16表示消息长度,所以缓冲区中至少有2个字节以上的数据时才去读取并处理,如果小于2,不足以解析出长度信息,如果大于2但小于消息长度+2,表示不足以读取到完整消息。

if (bufferCount <= 2) return;
Int16 length = BitConverter.ToInt16(readBuffer, 0);
if (bufferCount < length + 2) return;
//代码执行到此处表示已经有完整的消息,进行处理
string content = Encoding.UTF8.GetString(readBuffer, 2, length);

完整消息读取后,将缓冲区的后续数据向前移位,更新缓冲区。

int startIndex = 2 + length;
int count = bufferCount - startIndex;
Array.Copy(readBuffer, startIndex, readBuffer, 0, count);
bufferCount -= startIndex;

Socket TCP协议解决粘包、半包问题的三种解决方案相关推荐

  1. 网络:什么是TCP粘包/半包?怎么解决这个问题

    在socket网络编程中,都是端到端通信,由客户端端口+服务端端口+客户端IP+服务端IP+传输协议组成的五元组可以明确的标识一条连接.在TCP的socket编程中,发送端和接收端都有成对的socke ...

  2. TCP 粘包半包 netty 编解码 三者关系

    1 何为粘包 / 半包? 对方一次性接收了多条消息这种现象,我们就称之为 粘包现象. 对方多次接收了不完整消息这种现象,我们就称之为 半包现象. 粘包的原因: 发送方发送的消息 < 缓冲区大小 ...

  3. Netty如何解决粘包半包问题

    何为粘包 / 半包? 比如,我们发送两条消息:ABC 和 DEF,那么对方收到的就一定是 ABC 和 DEF 吗? 不一定,对方可能一次就把两条消息接收完了,即 ABCDEF:也可能分成了好多次,比如 ...

  4. 为什么tcp不采用停等协议_为什么 TCP 协议有粘包问题

    来自公众号:真没什么逻辑 链接:https://draveness.me/whys-the-design-tcp-message-frame/ 为什么这么设计(Why's THE Design)是一系 ...

  5. Netty框架之TCP粘包/半包解决方案

    Netty框架之TCP粘包/半包解决方案 一.TCP粘包 二.TCP半包 三.TCP粘包/半包解决方案 1.FixedLengthFrameDecoder定长解析器 2.LineBasedFrameD ...

  6. 三、Netty的粘包半包问题解决

    一.定义 TCP 传输中,客户端发送数据,实际是把数据写入到了 TCP 的缓存中,粘包和半包也就会在此时产生.客户端给服务端发送了两条消息ABC和DEF,服务端这边的接收会有多少种情况呢?有可能是一次 ...

  7. Netty粘包/半包问题解析

    目录 一.什么是粘包/半包问题 二.TCP粘包/半包发生的原因 三.粘包/半包解决办法 四.Netty中粘包/半包解决示例 1. 采用固定长度数据包编解码方式 2. 采用特殊字符作为边界字符编解码方式 ...

  8. websocket是否需要处理粘包半包问题分析

    结论: ​ 不需要. 背景: ​ 公司通信涉及到websocket相关,我们都知道websocket是基于tcp的,而tcp是面向字节流的,是需要处理粘包半包问题的.那么websocket是否需要处理 ...

  9. netty——黏包半包的解决方案、滑动窗口的概念

    黏包半包 滑动窗口 在深入理解黏包半包问题之前,先了解TCP的一个知识点--滑动窗口 我们都指定tcp是一种可靠的传输协议,这主要是因为在tcp中客户端给服务器端发送一条消息,要等待服务器端的应答,如 ...

最新文章

  1. predicate 列存储索引扫描_在SQL SERVER中导致索引查找变成索引扫描的问题分析
  2. 三层神经网络前向后向传播示意图
  3. java ecdh算法_椭圆曲线ECC ECDH原理 javacard实现
  4. 中标麒麟/NeoKylin 安装QT开发环境
  5. [Linux] 内核模块proc使用 实例:统计所有进程的信息
  6. [转载] Python pep8编码规范
  7. openim php sdk,imsdk_restapi-php-sdk
  8. mysql读写分离 保持数据一致性_读写分离数据库如何保持数据一致性
  9. java正则卡号4位一空格_银行卡号每隔4位插入空格
  10. BS结构浏览器网页读写IC卡技术汇总
  11. javascript弹窗和基本数据类型
  12. 版本控制系统(vcs)Git
  13. 基于三星 bada 手机操作系统 的打泡泡游戏
  14. 中国石油沥青行业市场供需与战略研究报告
  15. 自然语言处理(NLP)概论
  16. MODBUS TCP/IP通信协议及测试方法
  17. SQL INSERT INTO的用法
  18. 谷歌出品,数据集搜索引擎上线了!
  19. treeGrid 的使用( EasyUI )
  20. 怎么看待ChatGPT封号这件事呢?

热门文章

  1. 果快服务器维护中 稍后再试,维护中什么意思?服务维护中是什么意思
  2. [ BZOJ 2757 ]Blinker的仰慕者
  3. 斗鱼虎牙合并:从内耗走向一致抗敌
  4. transporter上传卡正在交付_Xcode11或Transporter上传app store 一直卡在Authenticating with the App Store 的解决...
  5. 企业WiFi管理解决方案
  6. OllyDBG 寄存器窗口
  7. PoE供电交换机的五大优势详解
  8. (附源码)ssm教学督导管理系统 毕业设计 292346
  9. 2002年世界杯中国队男足的3场比赛(中国vs哥斯达黎加、巴西和土耳其)比分
  10. 我和Double Lift的故事(三)——应用篇