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粘包拆包问题 什么是粘包 - 拆包问题 为什么存在粘包 - 拆包问题 粘包 - 拆包 演示 粘包 - 拆包 解决方案 方式一: 固定缓冲区大小 方式二: 封装请求协议 方式三: 特殊字符结 ...
随机推荐
- 【SSH】——Hibernate实现简单的自动建表
[与ORM] Object Relational Mapping,对象关系映射,将对象和关系联系了起来.面向对象是从耦合.聚合.封装等的基础上发展起来的,而关系数据库则是从数学理论发展而来的,两套理论 ...
- 在es中用scroll查询与completableFuture
一般而言,es返回数据的上限是10000条,如果超过这个数量,就必须使用scroll查询. 所谓scroll查询就类似DBMS中的游标,或者快照吧,利用查询条件,在第一次查询时,在所有的结果上形成了一 ...
- 【bzoj3000】Big Number 数论
题目描述 给你两个整数N和K,要求你输出N!的K进制的位数. 输入 有多组输入数据,每组输入数据各一行,每行两个数——N,K 输出 每行一个数为输出结果. 样例输入 2 5 2 10 10 10 10 ...
- 【bzoj1951】[Sdoi2010]古代猪文 费马小定理+Lucas定理+中国剩余定理
题目描述 求 $g^{\sum\limits_{k|n}C_{n}^{\frac nk}}\mod 999911659$ 输入 有且仅有一行:两个数N.G,用一个空格分开. 输出 有且仅有一行:一个 ...
- Ubuntu下Eclipse中运行Hadoop程序的参数问题
需要统一的参数: 当配置好eclipse中hadoop的程序后,几个参数需要统一一下: hadoop安装目录下/etc/core_site.xml中 fs.default.name的端口号一定要与ha ...
- Seajs的用法
以前经常听到Seajs,但是没深入了解过,不清楚到底是用做哪个方面,后来调组到M站做开发,发现项目用到了Seajs,便去了解下 SeaJS是一个遵循CMD规范的JavaScript模块加载框架,可以实 ...
- Spring源码解析-事件
Spring事件的组件 主要是3个组件: 1.ApplicationEvent 事件 2.ApplicationListener 监听器,对事件进行监听 3.ApplicationEventMul ...
- last_query_cost
The total cost of the last compiled query as computed by the query optimizer. This is useful for com ...
- HDU 1203 01背包
I NEED A OFFER! Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)T ...
- OpenCV+Java环境搭建
1.官网地址http://opencv.org/ 1.首先下载OpenCV2.4.6,下载的时候,选择windows版的.然后安装 2.其实安装的过程就是解压的过程,并没有什么安装向导之类的,安装完成 ...