TCP通讯处理粘包详解
TCP通讯处理粘包详解
一般所谓的TCP粘包是在一次接收数据不能完全地体现一个完整的消息数据。TCP通讯为何存在粘包呢?主要原因是TCP是以流的方式来处理数据,再加上网络上MTU的往往小于在应用处理的消息数据,所以就会引发一次接收的数据无法满足消息的需要,导致粘包的存在。处理粘包的唯一方法就是制定应用层的数据通讯协议,通过协议来规范现有接收的数据是否满足消息数据的需要。在应用中处理粘包的基础方法主要有两种分别是以4节字描述消息大小或以结束符,实际上也有两者相结合的如HTTP,redis的通讯协议等。
在平时交流过程发现一些朋友即使做了这些协议的处理,但有时在处理数据的时候也会出现数据不对的情况。这主要原因他们在一些个别情况下没有处理好。因为当一系列的消息发送过来的时候,对于4节字头或结束符分布位置都是不确定的。一种简单的情况就是当前消息处理完成后,紧接着就是处理一下个消息的4节字描述,但在实际情况下当前接收的buffer剩下的内容有可能不足4节字的。如果你想通过通讯的程序来测这情况相对来说触发的机率性不高,所以对于协议分析的功能最好通过单元测试来模拟。
通过下面这个图可以更清晰地了解协议标记数据分布的情况
下面简单地介绍一下4字节描述大小和结束符和处理方式。
4字节大小描述方式
1 public void Import(byte[] data, int start, int count)
2 {
3 while (count > 0)
4 {
5 if (!mLoading)
6 {
7 mCheckSize.Reset();
8 mStream.SetLength(0);
9 mStream.Position = 0;
10 mLoading = true;
11 }
12 if (mCheckSize.Length == -1)
13 {
14 while (count > 0 && mCheckSize.Length == -1)
15 {
16 mCheckSize.Import(data[start]);
17 start++;
18 count--;
19 }
20 }
21 else
22 {
23 if (OnImport(data, ref start, ref count))
24 {
25 mLoading = false;
26 if (Receive != null)
27 {
28 mStream.Position = 0;
29 Receive(mStream);
30 }
31 }
32 }
33 }
34 }
35
36
37 public void Import(byte value)
38 {
39 LengthData[mIndex] = value;
40 if (mIndex == 3)
41 {
42 Length = BitConverter.ToInt32(LengthData, 0);
43 if (!LittleEndian)
44 Length = Endian.SwapInt32(Length);
45 }
46 else
47 {
48 mIndex++;
49 }
50 }
代码很简单如果没有长度描述的情况就把数据导入到消息长度描述的buffer中,如果当前buffer满足4位的情况直接得到相应长度。后面的工作就是获取相应长度的buffer即可。
结束符方式
1 public void Import(byte[] data, int start, int count)
2 {
3 while (count > 0)
4 {
5 if (!mLoading)
6 {
7 mStream.SetLength(0);
8 mStream.Position = 0;
9 mLoading = true;
10 }
11 if (data[x] == mEof[0])
12 {
13 start += mEof.Length;
14 count -= mEof.Length;
15 mLoading = false;
16 if (Receive != null)
17 {
18 mStream.Position = 0;
19 Receive(mStream);
20 }
21 }
22 else
23 {
24 mStream.Write(data[start]);
25 start++;
26 count--;
27 }
28 }
29 }
结束符的处理方式就相对来说简单多了。
以上就是两种TCP数据处理粘包的情况,相关代码紧供参考。
开源数据库访问组件
开源多台平通讯组件
c#组件设计交流群:47164588
c# socket :136485198 微博http://weibo.com/ikende
TCP通讯处理粘包详解的更多相关文章
- ip头、tcp头、udp头详解及定义,结合Wireshark抓包看实际情况
公司的同事们在分析网页加载慢的问题,忽然使用到了Wireshark工具,我就像发现新大陆一样好奇,赶紧看了看,顺便复习了一下相关协议.上学时学的忘的差不多了,汗颜啊! 报文封装整体结构 mac帧头定义 ...
- 常见 jar包详解
常见 jar包详解 jar包 用途 axis.jar SOAP引擎包 commons-discovery-0.2.jar 用来发现.查找和实现可插入式接口,提供一些一般类实例化.单件的生命周期 ...
- 2.TCP_IP互联线缆_TCP_UDP报文抓包详解
TCP_IP互联线缆_TCP_UDP报文抓包详解 2.1网线标准 直通线 交叉线 异种设备互联使用直通线 同种设备互联使用交叉线 TCP和UDP 端口寻址 TCP数据格式 TCP三次握手 UDP数据格 ...
- 有关TCP和UDP 粘包 消息保护边界
http://www.cnblogs.com/lancidie/archive/2013/10/28/3392428.html 在socket网络程序中,TCP和UDP分别是面向连接和非面向连接的.因 ...
- 第二十八天- tcp下的粘包和解决方案
1.什么是粘包 写在前面:只有TCP有粘包现象,UDP永远不会粘包 1.TCP下的粘包 因为TCP协议是面向连接.面向流的,收发两端(客户端和服务器端)都要有成对的socket,因此,发送端为了将多个 ...
- 网络编程之tcp协议以及粘包问题
网络编程tcp协议与socket以及单例的补充 一.单例补充 实现单列的几种方式 #方式一:classmethod # class Singleton: # # __instance = None # ...
- TCP报文段首部格式详解
TCP首部格式 格式字段详解 源端口.目标端口: 计算机上的进程要和其他进程通信是要通过计算机端口的,而一个计算机端口某个时刻只能被一个进程占用,所以通过指定源端口和目标端口,就可以知道是哪两 ...
- 为什么 TCP 协议有粘包问题
为什么 TCP 协议有粘包问题 这部分转载自draveness博客. TCP/IP 协议簇建立了互联网中通信协议的概念模型,该协议簇中的两个主要协议就是 TCP 和 IP 协议.TCP/ IP 协议簇 ...
- Spring jar包详解
Spring jar包详解 org.springframework.aop ——Spring的面向切面编程,提供AOP(面向切面编程)的实现 org.springframework.asm——spri ...
随机推荐
- 虚拟WiFi
转载用WinForm写一个虚拟WiFi助手玩玩(附源码) 这早不是什么新鲜的东西了,同类软件已经有很多,但不是收费就是有广告,在学校的时候就想自已写一个了,但那时候啥也没学,对C的掌握程度也就是定 ...
- 【百度地图API】如何激发手机的高分辨率
原文:[百度地图API]如何激发手机的高分辨率 摘要:不少用户使用百度地图API开发在移动浏览器上的应用时发现,明明自己的手机是高分辨率的,但是显示出来的地图却比较模糊,甚至“看不清楚”.接下来,我们 ...
- Vim实用小技巧
Vim实用小技巧 一些网络上质量较高的Vim资料 从我07年接触Vim以来,已经过去了8个年头,期间看过很多的Vim文章,我自己觉得非常不错,而且创作时间也比较近的文章有如下这些. Vim入门 目前为 ...
- JS判断Array数组中是否包含指定元素
1.调用方式: var arr=["a","b"]; alert(arr.in_array("a")) 2.JS判断数组是否包含指定元素方法 ...
- Objective-c中的单例
单例是指静态分配的实例,就是只开辟一块内存,不会重新开辟内存,而 iphone sdk 中全是这种实例,例如[UIApplication sharedApplication] 返回一个指向代表应用程序 ...
- 当有多于64合乎逻辑的cpu时刻,Windows 下一个Oracle db 实例启动(startup)什么时候会hang(待定)
Bug 9772171 - Database startup hangs on Windows when machine has more than 64 cores [ID 9772171.8] 该 ...
- 完整的thinphp+phpexcel实现excel报表的输出(有图有效果)
准备工作:1.下载phpexcel1.7.6类包:2.解压至TP框架的ThinkPHP\Vendor目录下,改类包文件夹名为PHPExcel176,目录结构如下图: 编写代码(以一个订单汇 ...
- VMware Workstation 无法与 Windows XP \ Windows 7 \ Windows 8 进行共享文件夹。
1.这是一个小Bug,做法很简单. ----①.如果安装了VMware Tools,先卸载VMware Tools,重启虚拟机,再安装VMware Tools,重启虚拟机,就行了. ----②.如果没 ...
- Ubuntu Ruby On Rails安装和配置
在这篇文章中ubuntu通过rvm安装ruby和rails.步借鉴了官方网站和网上信息,这里给大家分享. 1. 安装mapapis公钥: gpg --keyserver hkp://keys.gnup ...
- java 学习List 的 add 与set差分法
/** * 在List收集在许多方面.add(int index,Object obj)方法与set(int index,Object e)方法不易区分 * .通过以下实例.能够看出两个方法中的差别 ...