2014年与宗宗一起去厦门测试软件接口的时候,与上级系统基于TCP方式通讯,数据量大时,经常通讯失败,检查日志发现是上级系统应该多次返回的数据一次性接收到了。

上网搜索了一下,才了解到TCP粘包的问题。摘录如下:

UDP丢包是因为数据包在传送过程中丢失了,而TCP是基于流式的发送,并且存在丢包重发机制,TCP是可靠连接而UDP是不可靠的。

正是由于TCP是流式传送的,也就是连接建立后可以一直不停的发送,并没有明确的边界定义,而用UDP发送的时候,是可以按照一个一个数据包去发送的,一个数据包就是一个明确的边界。
而TCP并没有数据包的概念,是完全流式的,他会开辟一个缓冲区,发送端往其中写入数据,每过一段时间就发送出去,然后接收端接收到这些数据,但是并不是说我发送了一次数据就肯定发送出去了,数据会在缓冲区中,有可能后续发送的数据和之前发送的数据同时存在缓冲区中随后一起发送,这就是粘包的一种形式。接收端也有产生粘包的情况,如果应用程序没有及时处理缓冲区中的数据,那么后续到达的数据会继续存放到缓冲区中,也就是2次接收的数据同时存在缓冲区中,下次取缓冲区的时候就会取出2次粘包后的数据,这是粘包的另外一种形式。还有其他许多形式,比如填充缓冲区到一半缓冲区满了直接发送了 但是其实那个包还没填充完全,这个就是不完整的粘包了,剩余数据会在下次发送的时候补上。

关于解决方法:如果你是连续的整个数据流,比如发送文件,那么完全不考虑粘包也无所谓,因为可以建立连接后发送,发送完毕后断开连接,整个数据流就是整个一个文件,无论数据从哪里切开都无所谓,整个拼接后依旧是整个一个文件的数据。
如果你发送的数据是多次通信,比如把一个目录下所有的文件名都发送过去,那么就不能当作一个整体发送了,必须对他们划分边界,有一个很简单的处理方法,就是采用"数据长度+实际数据"的格式来发送数据,这个"数据长度"的格式是固定宽度的,比如4字节,可以表示0~4GB的宽度了,足够用了,这个宽度说明了后续实际数据的宽度,这样你就可以把粘包后的数据按照正确的宽度取出来了。
每次都是取出4字节,随后按照正确的宽度取出后续部分的就OK了。
如果你的所有数据都是固定宽度的,比如不停的发送温度数据,每个都是1字节,那么宽度已知了,每次你都取出一个1字节就OK了,所以就不用发送宽度数据了。
当然你也可以按照建立连接断开连接来划分边界,每次发送数据都打开、关闭一次连接,不过对于频繁的小数据量是不可取的做法,因为开销太大,建立连接和关闭连接也是需要耗费网络流量的。
总而言之,粘包的情况是无法绝对避免的,因为网络环境是很复杂的,依赖发送和接收缓冲区的控制是不能保证100%的,只要在发送的数据中说明数据的宽度随后在接收部分按照这个宽度拆开就OK了,宽度全都是统一的,已知宽度的情况下拆开更加容易,连在发送端填入宽度数据都可以省去了。

 本文用菊子曰发布

关于TCP的粘包的更多相关文章

  1. TCP的粘包现象

    看面经时,看到有面试官问TCP的粘包问题.想起来研一做购物车处理数据更新时遇到粘包问题,就总结一下吧. 1 什么是粘包现象 TCP粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看, ...

  2. TCP拆包粘包之分隔符解码器

    TCP以流的方式进行数据传输,上层的应用协议为了对消息进行区分,往往采用如下4种方式. (1)消息长度固定,累计读取到长度总和为定长LEN的报文后,就认为读取到了一个完整的消息:将计数器置位,重新开始 ...

  3. python 网络编程之TCP传输&粘包传输

    只有TCP有粘包现象,UDP永远不会粘包. 所谓粘包问题主要还是C/S两端数据传输时 因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的 根本原因:粘包是由TCP协议本身造成的,T ...

  4. python 全栈开发,Day35(TCP协议 粘包现象 和解决方案)

    一.TCP协议 粘包现象 和解决方案 黏包现象让我们基于tcp先制作一个远程执行命令的程序(命令ls -l ; lllllll ; pwd)执行远程命令的模块 需要用到模块subprocess sub ...

  5. TCP通信粘包问题分析和解决

    转载至https://www.cnblogs.com/kex1n/p/6502002.html 在socket网络程序中,TCP和UDP分别是面向连接和非面向连接的.因此TCP的socket编程,收发 ...

  6. TCP通信粘包问题分析和解决(全)(转)

    TCP通信粘包问题分析和解决(全) 在socket网络程序中,TCP和UDP分别是面向连接和非面向连接的.因此TCP的socket编程,收发两端(客户端和服务器端)都要有成对的socket,因此,发送 ...

  7. Netty—TCP的粘包和拆包问题

    一.前言 虽然TCP协议是可靠性传输协议,但是对于TCP长连接而言,对于消息发送仍然可能会发生粘贴的情形.主要是因为TCP是一种二进制流的传输协议,它会根据TCP缓冲对包进行划分.有可能将一个大数据包 ...

  8. C/C++ socket编程教程之九:TCP的粘包问题以及数据的无边界性

    C/C++ socket编程教程之九:TCP的粘包问题以及数据的无边界性 上节我们讲到了socket缓冲区和数据的传递过程,可以看到数据的接收和发送是无关的,read()/recv() 函数不管数据发 ...

  9. TCP协议粘包问题详解

    TCP协议粘包问题详解 前言 在本章节中,我们将探讨TCP协议基于流式传输的最大一个问题,即粘包问题.本章主要介绍TCP粘包的原理与其三种解决粘包的方案.并且还会介绍为什么UDP协议不会产生粘包. 基 ...

随机推荐

  1. mysql 循环插入日期递增

    create procedure wk() begin declare i int; ; do insert into t (myday) values (date_sub(curdate(),int ...

  2. H5-表格、表单

    一.表格 1.表格标签 a.table 表格 b.thead 表格头 c.tbody 表格主体 d.tr 表格行 e.th 元素定义表头 f.td 元素定义表格单元 2.表格样式重置 a.table{ ...

  3. SQL Server 查看物理页存储

    创建测试表 Use Test create table dbo.employee( emp_lname varchar(12) not null, emp_fname varchar(12)not n ...

  4. hihoCoder 1305 区间求差

    #1305 : 区间求差 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定两个区间集合 A 和 B,其中集合 A 包含 N 个区间[ A1, A2 ], [ A3,  ...

  5. QEMU/KVM功能测试

    最近在对QEMU/KVM在HP服务器进行功能测试,项目刚刚启动,遇到不少问题,从Git上拿到最新的source build进行测试,在RHEL7.0a3 + Kernel version3.10 + ...

  6. java的面向对象

    Java是1995年诞生.前身oak,后来改名为java. 面向对象的编程思想:对象是万事万物. 对象是由两部分组成的:属性和方法 1:属性是对象的静态特性(名词) 2:方法是对象的动态特性(动词) ...

  7. three.js 之旅 (五)--跟场景scene相关的函数

    1.scene.add(obj);   在场景中添加物体 2.scene.remove(obj);   在场景中移除物体 3.scene.children();  获取场景中所有子对象的列表 4.sc ...

  8. HDU 5023 A Corrupt Mayor's Performance Art (据说是线段树)

    题意:给定一个1-n的墙,然后有两种操作,一种是P l ,r, a 把l-r的墙都染成a这种颜色,另一种是 Q l, r 表示,输出 l-r 区间内的颜色. 析:应该是一个线段树+状态压缩,但是我用s ...

  9. WPF RichTextBox,关键字搜索,样式改变,超链接替换,图文混排

    RichTextBox 只是一个控件,表示对 FlowDocument 对象执行操作的丰富编辑控件.它所承载的内容由其 Document 属性来呈现. Document 是一个 FlowDocumen ...

  10. 【03_136】Single Number

    感谢:http://www.cnblogs.com/changchengxiao/p/3413294.html Single Number Total Accepted: 103007 Total S ...