tcp传输黏包

tcpip协议使用"流式"(套接字)进行数据的传输,就是说它保证数据的可达以及数据抵达的顺序,但并不保证数据是否在你接收的时候就到达,特别是为了提高效率,充分利用带宽,底层会使用缓存技术,具体的说就是使用Nagle算法将小的数据包放到一起发送,但是这样也带来一个使用上的问题——黏包,黏包就是说一次将多个数据包发送出去,导致接收方不能进行正常的解析,示意图如下:

发生黏包一般有两种原因,一种是发送方进行了不该缓冲的缓冲,比如上图中,收发双方协议好按照一定的规则进行编写/解析报文,但是由于Nagle算法,可能出现发送方一次发送了1.5个数据包,而接收方只解析了前面的1个包,后面的0.5个由于数据不完整而解析失败,造成数据的丢失或错位,很可能会影响之后所有的数据解析工作。由于发送方导致的黏包问题可以使用setsockopt()来解决

int enable=1;
setsockopt(sockfd,IPROTO_TCP,TCP_NODELAY,(void*)&enable,sizeof(enable))

这条指令可以禁止发送方使用Nagle算法,一组数据被写入就会立即被发出,不需要等待mtu被填满。

此外,接收方处理不当也可能导致黏包问题,如果发送方将4个包发送到接收方的缓冲区,但是由于频繁的存取,可能有一次只取了2.5个包,就会导致黏包问题。接收方的黏包问题可以使用recv(sockfd,buf,sizeof(buf),MSG_WAITALL)来解决,MSG_WAITALL可以强制接收方收到sizeof(buf)那么多的数据才返回,而buf的大小可以是收发双方约定好的大小。
发送一次发送这么多,接收一次接收这么多,就可以避免黏包问题。

上述方法可以解决带有解析需求的黏包问题,对于不需要解析的需求,比如文件传输,发送方需要发送100kB的文件,接收方其实只关心最终接收到100KB没有,至于中间的某次发送方发了100byte而接收方收到20byte并不会影响文件的传输,对于这样的需求,一种更好的方案是发送方在发送文件数据之前先将文件的大小告知给接收方,接收方准备好后一直读取数据,知道接收到文件的大小那么多的数据就自行终止写文件。这样就免去了不必要的解析,是否黏包已经不影响功能了。具体实施可以参考这个迷你云存储。

 

tcp传输黏包的更多相关文章

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

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

  2. Python—TCP的黏包问题以及UDP的分片问题

    TCP协议与UDP协议 TCP(transport control protocol,传输控制协议)是面向连接的,面向流的,提供高可靠性服务.收发两端(客户端和服务器端)都要有一一成对的socket, ...

  3. TCP黏包问题

    什么是黏包?什么情况下会出现黏包的情况?该如何避免黏包的情况? 首先来看一个例子 #服务端 import time from socket import * server = socket(AF_IN ...

  4. 黏包-黏包的成因、解决方式及struct模块初识、文件的上传和下载

    黏包: 同时执行多条命令之后,得到的结果很可能只有一部分,在执行其他命令的时候又接收到之前执行的另外一部分结果,这种显现就是黏包. 只有TCP协议中才会产生黏包,UDP协议中不会有黏包(udp协议中数 ...

  5. 铁乐学Python_Day34_Socket模块2和黏包现象

    铁乐学Python_Day34_Socket模块2和黏包现象 套接字 套接字是计算机网络数据结构,它体现了C/S结构中"通信端点"的概念. 在任何类型的通信开始之前,网络应用程序必 ...

  6. python socket编程和黏包问题

    一.基于TCP的socket tcp是基于链接的,必须先启动服务端,然后再启动客户端去链接服务端,有顺序,不重复,可靠.不会被加上数据边界. server端 import socket sk = so ...

  7. Python--day32--复习:https和http的区别;黏包;黏包问题的解决方式;

    1,https和http的区别: https比较安全,传输的时候先对内容进行加密,收到后再进行解密:它的传输内容不容易拦截,就算拦截下来了,也是加密的,看不懂.但是要买证书,一年要好几万,小公司承担不 ...

  8. python 黏包现象

    一.黏包 1.tcp有黏包现象 表现两种情况 发送的数据过小且下面还有一个发送数据,这两个数据会一起发送 发送的数据过大,超过最大缓存空间,超出的部分在下一次发送的时候发送 原因: tcp是面向流的, ...

  9. 2、网络并发编程--套接字编程、黏包问题、struct模块、制作简易报头、上传文件数据

    昨日内容回顾 面向对象复习(json序列化类) 对象.类.父类的概念 三大特性:封装 继承 多态 双下开头的方法(达到某个条件自动触发) __init__:对象实例化自动触发 __str__:对象执行 ...

随机推荐

  1. 前端开发中的SEO

    什么是SEO SEO由英文Search Engine Optimization缩写而来,中文意译为"搜索引擎优化".SEO是指从自然搜索结果获得网站流量的技术和过程,是在了解搜索引 ...

  2. 苹果系列机型专业刷机,解锁,解ID

    如有软件开发需求,请留言或在猪八戒网主页留言http://home.zhubajie.com/8506525/,常年接收c.c++(vs2010.RAD studio xe5\RAD studio 2 ...

  3. RocketMQ学习记录

    RocketMQ是一款分布式.队列模型的消息中间件,具有以下特点: 1.能够保证严格的消息顺序 2.提供丰富的消息拉取模式 3.高效的订阅者水平扩展能力 4.实时的消息订阅机制 5.亿级消息堆积能力 ...

  4. wordpress代理设置

    打开wp-config.php,在页首加上以下语句: define('WP_PROXY_HOST', '192.168.84.101'); define('WP_PROXY_PORT', '8080' ...

  5. wget下载FTP的文件

    在Linux中我们怎么样实现wget来下载文件  下面例子 下载所有的py结尾的文件到当前目录 wget ftp://anymous:anymous@42.51.152.2/soft/*.py 递归的 ...

  6. 学习实践:使用模式,原则实现一个C++自动化测试程序

    个人编程中比较喜欢重构,重构能够提高自己的代码质量,使代码阅读起来也更清晰.但是重构有一个问题,就是如何保证重构后带代码实现的功能与重构前的一致,如果每次重构完成后,对此不闻不问,则会有极大的风险,如 ...

  7. mariadb的select语句

    mariadb的查询流程图 select语句的从句分析顺序:from(过滤表)-->where(过滤行)-->group by(分组)-->having(分组过滤)-->ord ...

  8. php根据日期获得星期

    <?php $weekarray=array("日","一","二","三","四",&quo ...

  9. IE PNG格式的图片不现实的的解决方法

    可能是安装某些软件导致注册表缺失png的一些设置 ,网上找了好些办法都是修改注册表的. 终于找到傻瓜式的解决方法:将下面的代码复制到txt中 另存为reg后缀格式,双击运行即可,然后重新打开IE 完事 ...

  10. linux内核SPI总线驱动分析(一)(转)

    linux内核SPI总线驱动分析(一)(转) 下面有两个大的模块: 一个是SPI总线驱动的分析            (研究了具体实现的过程) 另一个是SPI总线驱动的编写(不用研究具体的实现过程) ...