关于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协议不会产生粘包. 基 ...
随机推荐
- Java学习笔记16--异常
异常 异常是导致程序中断运行的一种指令流,如果不对异常进行正确的处理,则可能导致程序的中断执行,造成不必要的损失, 所以在程序的设计中必须要考虑各种异常的发生,并正确的做好相应的处理,这样才能保证程序 ...
- [z]vs中无法加入断点进行调试的解决方案
http://blog.chinaunix.net/uid-15464162-id-3799069.html [ 1] 以前也遇到过同样的问题,但没有问个为什么,也没有探个毕竟.昨天调试一个DLL,添 ...
- Sql Server 2008修改Sa密码
1.用Windows验证模式进入数据库管理器 右键根目录 >>>>属性>>>>左边的安全性 选择sql server 和windows 验证(SQL S ...
- 20145225唐振远 实验二 "Java面向对象程序设计"
20145225<Java程序设计> 实验二 Java面向对象程序设计 实验报告 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S ...
- EditText 焦点
让EditText不自动获取焦点,只需要在EditText的父控件加上 android:focusable="true"android:focusableInTouchMode=& ...
- 【洛谷P1351】联合权值
我们枚举中间点,当连的点数不小于2时进行处理 最大值好搞 求和:设中间点 i 所连所有点权之和为sum 则对于每个中间点i的联合权值之和为: w[j]*(sum-w[j])之和 #include< ...
- React与ES6(三)ES6类和方法绑定
React与ES6系列: React与ES6(一)开篇介绍 React和ES6(二)ES6的类和ES7的property initializer React与ES6(三)ES6类和方法绑定 React ...
- WCF配置与服务寄宿
1.项目框架如下: 2.WCF服务项目 其中WCFService中存放服务契约及其实现,需添加命名空间:System.ServiceModel 3.服务寄宿 WCFHost是一个控制台程序,用于寄宿W ...
- Hibernate配置文件与映射文件的创建
1. config文件的创建: 内容: <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE hib ...
- 人脸识别经典算法一:特征脸方法(Eigenface)
这篇文章是撸主要介绍人脸识别经典方法的第一篇,后续会有其他方法更新.特征脸方法基本是将人脸识别推向真正可用的第一种方法,了解一下还是很有必要的.特征脸用到的理论基础PCA在另一篇博客里:特征脸(Eig ...