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. win7启动文件修复

    1:在xp下运行bcdedit.exe(这软件在windows 7的系统盘下 就在你的c:\windows\system32\这里2:将这软件复制到c盘根目录下3:进入命令提示符 输入 c:4:输入 ...

  2. C#时间处理--DateTime和TimeSpan

    DateTime dt = DateTime.Now; dt.ToString();//2005-11-5 13:21:25 dt.ToFileTime().ToString();//12775641 ...

  3. 修改 Ueditor 默认显示的字体大小

    默认字体为16px,有点大,为了美观而且一屏可以显示更多内容,可以修改为12px 打开:ueditor.all.min.js 我用的是压缩版 找到如下代码: body{margin:8px;font- ...

  4. 怎样在Android中ListView与ArrayAdapter配合使用

    [代码]main.xml   <?xml version="1.0" encoding="utf-8"?> <LinearLayout xml ...

  5. ububtu 14.04 问题集合

    作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4168168.html 1.Chromium 中的flash插件问题: sudo apt-ge ...

  6. Java----代码优化篇

    一.咱们之所以这么干的目的: 1.效率(最重要) 2.可读性,便于后期维护.(同样很重要) 二.代码优化的要求: 1.减小代码的体积. 2.提高代码的运行效率. 三.常用的代码的优化: 1.尽量重用对 ...

  7. nginx学习笔记1

    Nginx是使用c语言编写的,查看nginx编译时参数的设定  使用nginx -V命令查看 可以使用nginx -h命令查看命令帮助 配置文件中将worker process绑定到cpu的特定内核上 ...

  8. 如何用Ajax实现地址栏省市级联动(数据库表数据源)

    HTML: <tr> <th> <label for="textfield"><span class="red"> ...

  9. Python之Flask Web开发

    下载python包管理工具Pip: 访问网址:https://pip.pypa.io/en/stable/installing/    下载文件get-pip.py到本地计算机 定位到get-pip. ...

  10. for xml path('') 引发的数据不完整

    When you read Extensible Markup Language (XML) data from Microsoft SQL Server by using the SqlDataRe ...