TCP通讯处理粘包详解
2013-08-27 13:52
344 查看
一般所谓的TCP粘包是在一次接收数据不能完全地体现一个完整的消息数据。TCP通讯为何存在粘包呢?主要原因是TCP是以流的方式来处理数据,再加上网络上MTU的往往小于在应用处理的消息数据,所以就会引发一次接收的数据无法满足消息的需要,导致粘包的存在。处理粘包的唯一方法就是制定应用层的数据通讯协议,通过协议来规范现有接收的数据是否满足消息数据的需要。在应用中处理粘包的基础方法主要有两种分别是以4节字描述消息大小或以结束符,实际上也有两者相结合的如HTTP,redis的通讯协议等。
在平时交流过程发现一些朋友即使做了这些协议的处理,但有时在处理数据的时候也会出现数据不对的情况。这主要原因他们在一些个别情况下没有处理好。因为当一系列的消息发送过来的时候,对于4节字头或结束符分布位置都是不确定的。一种简单的情况就是当前消息处理完成后,紧接着就是处理一下个消息的4节字描述,但在实际情况下当前接收的buffer剩下的内容有可能不足4节字的。如果你想通过通讯的程序来测这情况相对来说触发的机率性不高,所以对于协议分析的功能最好通过单元测试来模拟。
通过下面这个图可以更清晰地了解协议标记数据分布的情况
下面简单地介绍一下4字节描述大小和结束符和处理方式。
代码很简单如果没有长度描述的情况就把数据导入到消息长度描述的buffer中,如果当前buffer满足4位的情况直接得到相应长度。后面的工作就是获取相应长度的buffer即可。
结束符的处理方式就相对来说简单多了。
以上就是两种TCP数据处理粘包的情况,相关代码紧供参考。
在平时交流过程发现一些朋友即使做了这些协议的处理,但有时在处理数据的时候也会出现数据不对的情况。这主要原因他们在一些个别情况下没有处理好。因为当一系列的消息发送过来的时候,对于4节字头或结束符分布位置都是不确定的。一种简单的情况就是当前消息处理完成后,紧接着就是处理一下个消息的4节字描述,但在实际情况下当前接收的buffer剩下的内容有可能不足4节字的。如果你想通过通讯的程序来测这情况相对来说触发的机率性不高,所以对于协议分析的功能最好通过单元测试来模拟。
通过下面这个图可以更清晰地了解协议标记数据分布的情况
下面简单地介绍一下4字节描述大小和结束符和处理方式。
4字节大小描述方式
public void Import(byte[] data, int start, int count) { while (count > 0) { if (!mLoading) { mCheckSize.Reset(); mStream.SetLength(0); mStream.Position = 0; mLoading = true; } if (mCheckSize.Length == -1) { while (count > 0 && mCheckSize.Length == -1) { mCheckSize.Import(data[start]); start++; count--; } } else { if (OnImport(data, ref start, ref count)) { mLoading = false; if (Receive != null) { mStream.Position = 0; Receive(mStream); } } } } } public void Import(byte value) { LengthData[mIndex] = value; if (mIndex == 3) { Length = BitConverter.ToInt32(LengthData, 0); if (!LittleEndian) Length = Endian.SwapInt32(Length); } else { mIndex++; } }
代码很简单如果没有长度描述的情况就把数据导入到消息长度描述的buffer中,如果当前buffer满足4位的情况直接得到相应长度。后面的工作就是获取相应长度的buffer即可。
结束符方式
public void Import(byte[] data, int start, int count) { while (count > 0) { if (!mLoading) { mStream.SetLength(0); mStream.Position = 0; mLoading = true; } if (data[x] == mEof[0]) { start += mEof.Length; count -= mEof.Length; mLoading = false; if (Receive != null) { mStream.Position = 0; Receive(mStream); } } else { mStream.Write(data[start]); start++; count--; } } }
结束符的处理方式就相对来说简单多了。
以上就是两种TCP数据处理粘包的情况,相关代码紧供参考。
相关文章推荐
- TCP通讯处理粘包详解
- TCP通讯处理粘包详解
- GO语言如何手动处理TCP粘包详解
- python TCP Socket的粘包和分包的处理详解
- c/c++网络编程 对象的传输 以及 TCP粘包处理 解析
- socket中tcp的断包、粘包处理方法
- 【Python】TCP Socket的粘包和分包的处理
- TCP粘包分析与处理
- Go语言中Tcp协议粘包问题处理
- IOS 详解socket编程[oc]粘包、半包处理
- TCP粘包问题的处理
- TCP之拥塞处理详解
- tcp 粘包处理 TCP_NODELAY
- TCP粘包的拆包处理
- TCP粘包分析与处理
- muduo库chat server对TCP粘包问题的处理
- golang中tcp socket粘包问题和处理
- 游戏开发中AS3和服务端通过socket通讯,如何处理粘包的问题
- tcp粘包,断包问题及处理
- 我所经历过的tcp“粘包”及其处理