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. [转] linux虚拟带库操作笔记

    原文来自:“王旺的书房” ---- http://blog.itpub.net/271063/viewspace-1059840/ 分类: Linux 查看设备[root@node1 ~]# lssc ...

  2. Web服务器Nginx多方位优化策略

    标签:性能 Web 架构 Nginx 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://dongsong.blog.51cto.co ...

  3. XE3随笔3:访问

    测试数据提前加入 Memo1 中: { "name": "张三", /* 注释 */ "age": 33, "sex": ...

  4. jquery基本选择器,一张页面全搞定

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. 解决Failed to load class "org.slf4j.impl.StaticLoggerBinder"

    Hibernate使用SLF4J API记录日志,所以在Hibernate的lib中,不再提供Log4J的包,而大部分框架依然使用Log4J记录日志,这样导致了兼容性问题. 解决办法,两步: 一.在编 ...

  6. dos 加用户

    net user lipeng 1qaz3EDC /addnet user zhangnan 1qaz3EDC /addnet localgroup "Remote Desktop User ...

  7. Java 第11章 类的无参方法

    类的无参方法 类的方法由哪几部分组成? 方法的定义: 1.访问权限修饰符 2.方法返回的数据类型 3.方法的名称 4.方法的主体 成员变量和局部变量的区别有那些? ~ 作用域不同 - 成员变量的作用域 ...

  8. Tomcat需要更改三个端口,才能在一台机器上搭载多个tomcat

    1.shutdown端口.port改成与原有的不同即可 2.8080端口,需要更改. 3.默认端口

  9. Nginx + tornado + supervisor部署

    参考链接:supervisor + Tornado + Nginx 使用详解, 用tornado ,Supervisord ,nginx架网站, tornado官方文档 项目文档树: . ├── ch ...

  10. React Native填坑之旅--ListView篇

    列表显示数据,基本什么应用都是必须.今天就来从浅到深的看看React Native的ListView怎么使用.笔者写作的时候RN版本是0.34. 最简单的 //@flow import React f ...