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并不会影响文件的传输,对于这样的需求,一种更好的方案是发送方在发送文件数据之前先将文件的大小告知给接收方,接收方准备好后一直读取数据,知道接收到文件的大小那么多的数据就自行终止写文件。这样就免去了不必要的解析,是否黏包已经不影响功能了。具体实施可以参考这个迷你云存储

Linux tcp黏包解决方案的更多相关文章

  1. netty]--最通用TCP黏包解决方案

    netty]--最通用TCP黏包解决方案:LengthFieldBasedFrameDecoder和LengthFieldPrepender 2017年02月19日 15:02:11 惜暮 阅读数:1 ...

  2. day 28 黏包及黏包解决方案

    1.缓冲区 每个socket被创建以后,都会分配两个缓冲区,输入缓冲区和输出缓冲区,默认大小都是8k,可以通过getsocket()获取,暂时存放传输数据,防止程序在发送的时候卡阻,提高代码运行效率. ...

  3. Python网络编程基础 ❷ 基于upd的socket服务 TCP黏包现象

    TCP的长连接 基于upd的socket服务 TCP黏包现象

  4. python 缓冲区 subprocess 黏包 黏包解决方案

    一.缓冲区 二.两种黏包现象 两种黏包现象: 1 连续的小包可能会被优化算法给组合到一起进行发送 黏包现象1客户端 import socket BUFSIZE = 1024 ip_prort = (' ...

  5. socketserver tcp黏包

    socket (套接字) tcp(黏包现象原因) 传输中由于内核区缓冲机制(等待时间,文件大小),会在 发送端 缓冲区合并连续send的数据,也会出现在 接收端 缓冲区合并recv的数据给指定port ...

  6. python tcp黏包和struct模块解决方法,大文件传输方法及MD5校验

    一.TCP协议 粘包现象 和解决方案 黏包现象让我们基于tcp先制作一个远程执行命令的程序(命令ls -l ; lllllll ; pwd)执行远程命令的模块 需要用到模块subprocess sub ...

  7. tcp黏包

    转载https://www.cnblogs.com/wade-luffy/p/6165671.html 无论是服务端还是客户端,当我们读取或者发送消息的时候,都需要考虑TCP底层的粘包/拆包机制. 回 ...

  8. python之黏包和黏包解决方案

    黏包现象主要发生在TCP连接, 基于TCP的套接字客户端往服务端上传文件,发送时文件内容是按照一段一段的字节流发送的,在接收方看来,根本不知道该文件的字节流从何处开始,在何处结束. 两种黏包现象: 1 ...

  9. day28 黏包及黏包解决方案

    今日主要内容: 一 .缓冲区 二.两种黏包现象 三.黏包现象的两种解决方案 四.打印进度条(补充的,了解即可) 1. 缓冲区 缓冲区的作用 : 将程序和网络解耦(这样做的好处是程序不会以为网速的快慢而 ...

随机推荐

  1. sql 索引 的建立

    (From:http://54laobaixing.blog.163.com/blog/static/57843681200952411133121/) 假设你想找书中的某一个句子.你可以一页一页地逐 ...

  2. springMVC学习笔记(一)-----springMVC原理

    一.什么是springmvc springMVC是spring框架的一个模块,springMVC和spring无需通过中间整合层进行开发. springMVC是一个基于mvc的web框架. Sprin ...

  3. mybatis入门基础(二)----原始dao的开发和mapper代理开发

    承接上一篇 mybatis入门基础(一) 看过上一篇的朋友,肯定可以看出,里面的MybatisService中存在大量的重复代码,看起来不是很清楚,但第一次那样写,是为了解mybatis的执行步骤,先 ...

  4. C语言分割字符串

    最近在做一道C语言题目的时候需要用到分割字符串,本来想自己手写的,也不会很麻烦,但想到其他语言都有分割字符串的库函数,C语言怎么会没有呢?所以,在网上搜了一搜,果然有这样的函数,还是很好用的,在此总结 ...

  5. Java aes加密C#解密的取巧方法

    摘要: 项目开发过程中遇到一个棘手的问题:A系统使用java开发,通过AES加密数据,B系统使用C#开发,需要从A系统获取数据,但在AES解密的时候遇到麻烦.Java的代码和C#的代码无法互通. Ja ...

  6. HtmlHelper拓展实现RadioList

    mvc中HtmlHelper可以帮助我们生成许多Html控件,但是没有类似DropDownList的RadioList,但是发现这些方法都是拓展方法,于是就想自己也拓展一个RadioList 从网上下 ...

  7. 无法为目标平台“Microsoft.Data.Tools.Schema.Sql.Sql120DatabaseSchemaProvider”创建扩展管理器

    很久没写博客了,这段时间情绪不那么稳定,还是心态的问题... 就简单写个问题的解决方法吧,其实最近遇到的问题蛮多的,就拿这个解决过后又遇到的来写吧. 正如标题一样:VS2013 无法为目标平台“Mic ...

  8. python读取文件的方法

    一. 通过readline 逐行读取: #--encoding:utf-8 with open("ha.conf","r",encoding='utf-8') ...

  9. oracle触发器详解

    触发器是许多关系数据库系统都提供的一项技术.在ORACLE系统里,触发器类似过程和函数,都有声明,执行和异常处理过程的PL/SQL块. 1.触发器类型 触发器在数据库里以独立的对象存储,它与存储过程和 ...

  10. luogg_java学习_10_异常_反射

    本文为博主辛苦总结,希望自己以后返回来看的时候理解更深刻,也希望可以起到帮助初学者的作用. 转载请注明 出自 : luogg的博客园 谢谢配合! 异常_反射 异常 异常就是导致程序中断执行的一段指令流 ...