关于TCP的粘包
2014年与宗宗一起去厦门测试软件接口的时候,与上级系统基于TCP方式通讯,数据量大时,经常通讯失败,检查日志发现是上级系统应该多次返回的数据一次性接收到了。
上网搜索了一下,才了解到TCP粘包的问题。摘录如下:
UDP丢包是因为数据包在传送过程中丢失了,而TCP是基于流式的发送,并且存在丢包重发机制,TCP是可靠连接而UDP是不可靠的。
正是由于TCP是流式传送的,也就是连接建立后可以一直不停的发送,并没有明确的边界定义,而用UDP发送的时候,是可以按照一个一个数据包去发送的,一个数据包就是一个明确的边界。
而TCP并没有数据包的概念,是完全流式的,他会开辟一个缓冲区,发送端往其中写入数据,每过一段时间就发送出去,然后接收端接收到这些数据,但是并不是说我发送了一次数据就肯定发送出去了,数据会在缓冲区中,有可能后续发送的数据和之前发送的数据同时存在缓冲区中随后一起发送,这就是粘包的一种形式。接收端也有产生粘包的情况,如果应用程序没有及时处理缓冲区中的数据,那么后续到达的数据会继续存放到缓冲区中,也就是2次接收的数据同时存在缓冲区中,下次取缓冲区的时候就会取出2次粘包后的数据,这是粘包的另外一种形式。还有其他许多形式,比如填充缓冲区到一半缓冲区满了直接发送了 但是其实那个包还没填充完全,这个就是不完整的粘包了,剩余数据会在下次发送的时候补上。
关于解决方法:如果你是连续的整个数据流,比如发送文件,那么完全不考虑粘包也无所谓,因为可以建立连接后发送,发送完毕后断开连接,整个数据流就是整个一个文件,无论数据从哪里切开都无所谓,整个拼接后依旧是整个一个文件的数据。
如果你发送的数据是多次通信,比如把一个目录下所有的文件名都发送过去,那么就不能当作一个整体发送了,必须对他们划分边界,有一个很简单的处理方法,就是采用"数据长度+实际数据"的格式来发送数据,这个"数据长度"的格式是固定宽度的,比如4字节,可以表示0~4GB的宽度了,足够用了,这个宽度说明了后续实际数据的宽度,这样你就可以把粘包后的数据按照正确的宽度取出来了。
每次都是取出4字节,随后按照正确的宽度取出后续部分的就OK了。
如果你的所有数据都是固定宽度的,比如不停的发送温度数据,每个都是1字节,那么宽度已知了,每次你都取出一个1字节就OK了,所以就不用发送宽度数据了。
当然你也可以按照建立连接断开连接来划分边界,每次发送数据都打开、关闭一次连接,不过对于频繁的小数据量是不可取的做法,因为开销太大,建立连接和关闭连接也是需要耗费网络流量的。
总而言之,粘包的情况是无法绝对避免的,因为网络环境是很复杂的,依赖发送和接收缓冲区的控制是不能保证100%的,只要在发送的数据中说明数据的宽度随后在接收部分按照这个宽度拆开就OK了,宽度全都是统一的,已知宽度的情况下拆开更加容易,连在发送端填入宽度数据都可以省去了。
本文用菊子曰发布关于TCP的粘包的更多相关文章
- TCP的粘包现象
看面经时,看到有面试官问TCP的粘包问题.想起来研一做购物车处理数据更新时遇到粘包问题,就总结一下吧. 1 什么是粘包现象 TCP粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看, ...
- TCP拆包粘包之分隔符解码器
TCP以流的方式进行数据传输,上层的应用协议为了对消息进行区分,往往采用如下4种方式. (1)消息长度固定,累计读取到长度总和为定长LEN的报文后,就认为读取到了一个完整的消息:将计数器置位,重新开始 ...
- python 网络编程之TCP传输&粘包传输
只有TCP有粘包现象,UDP永远不会粘包. 所谓粘包问题主要还是C/S两端数据传输时 因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的 根本原因:粘包是由TCP协议本身造成的,T ...
- python 全栈开发,Day35(TCP协议 粘包现象 和解决方案)
一.TCP协议 粘包现象 和解决方案 黏包现象让我们基于tcp先制作一个远程执行命令的程序(命令ls -l ; lllllll ; pwd)执行远程命令的模块 需要用到模块subprocess sub ...
- TCP通信粘包问题分析和解决
转载至https://www.cnblogs.com/kex1n/p/6502002.html 在socket网络程序中,TCP和UDP分别是面向连接和非面向连接的.因此TCP的socket编程,收发 ...
- TCP通信粘包问题分析和解决(全)(转)
TCP通信粘包问题分析和解决(全) 在socket网络程序中,TCP和UDP分别是面向连接和非面向连接的.因此TCP的socket编程,收发两端(客户端和服务器端)都要有成对的socket,因此,发送 ...
- Netty—TCP的粘包和拆包问题
一.前言 虽然TCP协议是可靠性传输协议,但是对于TCP长连接而言,对于消息发送仍然可能会发生粘贴的情形.主要是因为TCP是一种二进制流的传输协议,它会根据TCP缓冲对包进行划分.有可能将一个大数据包 ...
- C/C++ socket编程教程之九:TCP的粘包问题以及数据的无边界性
C/C++ socket编程教程之九:TCP的粘包问题以及数据的无边界性 上节我们讲到了socket缓冲区和数据的传递过程,可以看到数据的接收和发送是无关的,read()/recv() 函数不管数据发 ...
- TCP协议粘包问题详解
TCP协议粘包问题详解 前言 在本章节中,我们将探讨TCP协议基于流式传输的最大一个问题,即粘包问题.本章主要介绍TCP粘包的原理与其三种解决粘包的方案.并且还会介绍为什么UDP协议不会产生粘包. 基 ...
随机推荐
- Pig Latin
function translate(str) { //return str; var list = ['a','e','i','o','u']; if(list.indexOf(str[0]) &g ...
- Winform中DockPanel(引用WeifenLuo.WinFormsUI.Docking.dll组件)的使用
WeiFenLuo.WinFormsUI.Docking.dll是开源项目DockPanel Suite的一个类库,可实现像Visual Studio的窗口停靠.拖拽等功能.WeifenLuo.Win ...
- 基于PHP使用rabbitmq实现消息队列
1.从github上面获取AMQP基于php的实现扩展 2.创建生产者 send.php 3.创建消费者 receive.php 4.在cli模式下 分别执行 send.php receive. ...
- 乐视云计算基于OpenStack的IaaS实践
本文作者岳龙广,现在就职于乐视云计算有限公司,负责IaaS部门的工作. 从开始工作就混在开源世界里,在虚拟化方面做过CloudStack/Ovirt开发,现在是做以OpenStack为基础的乐视云平台 ...
- Ubuntu上部署一个简单的Java项目
一.安装tomcat7,mysql,Java JDK,直接apt安装 $ sudo aptitude install tomcat7 $ -jdk openjdk--jre $ sudo aptitu ...
- C++中复制构造函数
复制构造函数 复制构造函数用于: 根据另一个同类型的对象显示或隐式初始化一个对象 复制一个对象,将它作为实参传给一个函数 从函数返回时复制一个对象 初始化顺序容器中的元素 根据元素初始化式列表初始化数 ...
- centos7 配置vnc
这是一个关于怎样在你的 CentOS 7 上安装配置 VNC 服务的教程.当然这个教程也适合 RHEL 7 .在这个教程里,我们将学习什么是 VNC 以及怎样在 CentOS 7 上安装配置 VNC ...
- go protobuf 安装
1.https://github.com/google/protobuf/releases/tag/v3.0.0 下载需要的版本,如果执行autogen.sh的过程中出现autoreconf not ...
- 125 Valid Palindrome
public class Solution { public boolean isPalindrome(String s) { if(s==null) return false; s=s.toLowe ...
- Replication--复制延迟的诊断和解决
要解决复制延迟问题,需要首先定位复制延迟发生点,再找出复制延迟的原因,再做相应处理. 复制延迟发生点:1. 发布服务器2. 分发服务器3. 订阅服务器4. 发布服务器与分发服务器和分发服务器与订阅服务 ...