TCP 粘包及其解决方案(zz)
首先,我们回顾一下 TCP 和 UDP 的头部信息:
具体说明看:http://www.cnblogs.com/aomi/p/7776582.html
我们知道,TCP 和 UDP 是 TCP/IP 协议族传输层中的两个具有代表性的协议。其中,TCP 是面向连接的复杂的、可靠的字节流传输协议,而 UDP 是面向无连接的简单的、不可靠的数据报传输协议。
“流”的概念就是指不间断的数据结构,可以把它想象成你们家里的自来水管道中的水流。什么意思呢?举个例子:TCP 发送端应用程序发送了10次100字节的消息,那么,在接收端的应用程序接收到的可能是一个1000字节的连续不间断的数据。但如果是 UDP 端口发送了一个100字节的消息,那么 UDP 接收端就会以100字节的长度来接收数据。正因为这样,我们可以看到 TCP 头部中并没有长度信息,而 UDP 头部包含长度信息。好了,现在你应该明白我们在创建套接字的时候,为什么 type 的类型是 SOCK_STREAM 和 SOCK_DGRAM 了吧!
正如文章标题所述,显然,你已经知道 UDP 数据包存在明确边界,是不存在粘包现象的,只有 TCP 才会出现粘包现象。那么,接下来我们逐步分析 TCP 的流传输特性所带来如粘包这样的一些问题及其解决方案。
按每次通信后是否闭关连接,可以分为两类情况:长连接和短连接。长连接——指的是客户端和服务端先建立通信连接,连接建立后不断开,然后再进行报文发送和接收。短连接——指的是客户端和服务端每进行一次报文收发交易时才进行通信连接,交易完毕后立即断开连接,比如 http 协议。
所以我们可以分析以下几种情况:
(1)如果利用 TCP 每次发送数据,就与对方建立连接,然后双方发送完一段数据后,就关闭连接,这样就不会出现粘包问题(因为只有一种数据结构)。
(2)如果发送数据无结构,如文件传输,这样发送端只管发送,接收端只管接收存储就行,也不用考虑粘包。
(3)如果双方建立连接,需要在连接后一段时间内发送多个不同结构的数据,这时候接收端收到就可能是一堆粘在一起的数据,这样接收端应用程序就傻了,到底是要干嘛?不知道,因为协议并没有规定这么诡异的数据。
那么,可以认为 TCP 粘包问题并不是对所有应用都造成困扰的,只是对那些长连接并且需要传输多种数据结构的应用造成影响。仔细分析会发现,除了粘包问题,其实还可能会出现多包、少包、半包、断包等情况。
针对这些问题,一般会有如下解决方法:
(1)调用发送函数之后都强制数据立即传送(PUSH 指令)。
(2)对于接收端引起的粘包,则可通过优化程序设计、精简接收进程工作量、提高接收进程优先级等措施,使其及时接收数据,从而尽量避免出现粘包现象。
(3)添加一个固定的消息头,该消息头包含数据长度信息,每次数据时先接收固定大小的消息头,再根据其携带的长度信息接收消息实体。也就是说,通过人为控制多次接收来避免粘包。
(4)设置 TCP_NODELAY 选项,禁止 Nagle 算法。
(5)设置 SO_RCVBUF 和 SO_SNDBUF 选项,根据应用需求修改一个合适的接收、发送缓冲区大小。
(6)添加报文分隔标识,比如发送报文是在末尾添加 '\n'
,同时接收端使用 recv() 函数接收报文,并且设置参数 flags 的值为 MSG_PEEK。注意:当 flags 参数的值设置为 MSG_PEEK 时,recv() 可以从 socket 缓存中读取数据,但是不会将缓存中该部分数据清除,但如果使用 read() 函数直接读取 socket 缓存区中的内容,会清空缓存区中的内容。假设两段报文粘包,read() 会清空缓存区中所有内容,从而导致后一段报文中的粘包的部分数据丢失。
实际上,上述的几种解决方法都有不足之处,并且不一定能够完全避免 TCP 粘包问题。所以还是需要根据实际应用来进行应用场景和性能方面的衡量。
参考:
【1】Socket粘包问题
【2】Socket/TCP粘包、多包和少包, 断包
【3】(经典)tcp粘包分析
【4】Linux 网络编程详解五(TCP/IP协议粘包解决方案二)
- 顶
- 1
- 踩
TCP 粘包及其解决方案(zz)的更多相关文章
- python中TCP粘包问题解决方案
TCP协议中的粘包问题 1.粘包现象 基于TCP写一个远程cmd功能 #服务端 import socket import subprocess sever = socket.socket() seve ...
- Netty4实战 - TCP粘包&拆包解决方案
Netty是目前业界最流行的NIO框架之一,它的健壮性.高性能.可定制和可扩展性在同类框架中都是首屈一指.它已经得到了成百上千的商业项目的验证,例如Hadoop的RPC框架Avro就使用了Netty作 ...
- Socket编程(4)TCP粘包问题及解决方案
① TCP是个流协议,它存在粘包问题 TCP是一个基于字节流的传输服务,"流"意味着TCP所传输的数据是没有边界的.这不同于UDP提供基于消息的传输服务,其传输的数据是有边界的.T ...
- TCP粘包问题及解决方案
① TCP是个流协议,它存在粘包问题 TCP是一个基于字节流的传输服务,"流"意味着TCP所传输的数据是没有边界的.这不同于UDP提供基于消息的传输服务,其传输的数据是有边界的.T ...
- 【游戏开发】网络编程之浅谈TCP粘包、拆包问题及其解决方案
引子 现如今手游开发中网络编程是必不可少的重要一环,如果使用的是TCP协议的话,那么不可避免的就会遇见TCP粘包和拆包的问题,马三觉得haifeiWu博主的 TCP 粘包问题浅析及其解决方案 这篇博客 ...
- 查漏补缺:socket编程:TCP粘包问题和常用解决方案(上)
1.TCP粘包问题的产生(发送端) 由于TCP协议是基于字节流并且无边界的传输协议,因此很容易产生粘包问题.TCP的粘包可能发生在发送端,也可能发生在接收端.发送端的粘包是TCP协议本身引起的,TCP ...
- 深入了解Netty【八】TCP拆包、粘包和解决方案
1.TCP协议传输过程 TCP协议是面向流的协议,是流式的,没有业务上的分段,只会根据当前套接字缓冲区的情况进行拆包或者粘包: 发送端的字节流都会先传入缓冲区,再通过网络传入到接收端的缓冲区中,最终由 ...
- TCP粘包问题的解决方案01——自定义包体
粘包问题:应用层要发送数据,需要调用write函数将数据发送到套接口发送缓冲区.如果应用层数据大小大于SO_SNDBUF,那么,可能产生这样一种情况,应用层的数据一部分已经被发送了,还有一部分还在 ...
- TCP 粘包 - 拆包问题及解决方案
目录 TCP粘包拆包问题 什么是粘包 - 拆包问题 为什么存在粘包 - 拆包问题 粘包 - 拆包 演示 粘包 - 拆包 解决方案 方式一: 固定缓冲区大小 方式二: 封装请求协议 方式三: 特殊字符结 ...
随机推荐
- 第十三次ScrumMeeting会议
第十三次Scrum Meeting 时间:2017/12/1 地点:咖啡馆 人员:策划组美工组 名字 完成的工作 计划工作 蔡帜 完成公式的基本策划,Bug数量产生机制设计 科技树方面机制确定 游心 ...
- Python 随笔01---列表
列表 1.取出列表中的元素方法?? 2.删除列表中的元素del.remove对比?? 3.linux 常用操作命令
- User Agent的学习
什么是User-Agent? User-Agent是一个特殊字符串头,被广泛用来标示浏览器客户端的信息,使得服务器能识别客户机使用的操作系统和版本,CPU类型,浏览器及版本,浏览器的渲染引擎,浏览器语 ...
- codeforce580c (dfs)
题目意思:给你一棵树,然后每个叶子节点会有一家餐馆,你讨厌猫,就不会走有连续超过m个节点有猫的路,然后问你最多去几家饭店 思路:直接DFS Example Input 4 11 1 0 01 21 3 ...
- 算法(2) Find All Numbers Disappeared in an Array
题目:整数数组满足1<=a[i]<=n(n是数组的长度),某些元素出现一次,某些元素出现两次,在数组a[i]中找到[1,n]区间中未出现的数字.比如输入[4,3,2,7,8,2,3,1], ...
- 玩转VFS(sys_open, overlayfs, rename)
带着问题学习dentry 1)文件删除时 dentry的结构是如何变化的?是直接设置无效的吗?如果此时正好有个访问是在要删除目录下的一个文件,这咋办呢? 2)内核document目录下级联式地使用 d ...
- Jira & filter & subscribe & issues
Jira & filter & subscribe & issues https://confluence.atlassian.com/search/?query=subscr ...
- 【bzoj1180】[CROATIAN2009]OTOCI LCT
题目描述 给出n个结点以及每个点初始时对应的权值wi.起始时点与点之间没有连边.有3类操作: 1.bridge A B:询问结点A与结点B是否连通.如果是则输出“no”.否则输出“yes”,并且在结点 ...
- Luogu2662 牛场围栏(最短路)
小凯的疑惑升级版的升级版.答案若存在不会超过30002-3000,暴力dp似乎勉强可以过.当然这不优美. 注意到如果能拼出长度为l的围栏,就一定能拼出长度为l+kx的围栏,其中x为最短的(或任意一个) ...
- 【题解】NOI2015寿司晚宴
想好久啊+不敢写啊……但果然人还是应当勇敢自信,只有坚定地去尝试,才会知道最后的结果.1A真的太开心啦,不过好像我的做法还是比较复杂的样子……理解起来应该算是比较容易好懂的类型,大家可以参考一下思路~ ...