关于Socket粘包、半包问题的解决方法
背景
在 Java 语言中,传统的 Socket 编程分为两种实现方式,这两种实现方式也对应着两种不同的传输层协议:TCP 协议和 UDP 协议。
但作为互联网中最常用的传输层协议 TCP,在使用时却会导致粘包和半包问题。
TCP协议
传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793 [1] 定义。
TCP旨在适应支持多网络应用的分层协议层次结构。 连接到不同但互连的计算机通信网络的主计算机中的成对进程之间依靠TCP提供可靠的通信服务。TCP假设它可以从较低级别的协议获得简单的,可能不可靠的数据报服务。 原则上,TCP应该能够在从硬线连接到分组交换或电路交换网络的各种通信系统之上操作。
TCP建立连接的三次握手流程:
TCP释放连接的四次挥手过程:
粘包问题
TCP粘包问题
TCP为了保证可靠传输,尽量减少额外开销(每次发包都要验证),因此采用了流式传输,面向流的传输,相对于面向消息的传输,可以减少发送包的数量。从而减少了额外开销。
但是,对于数据传输频繁的程序来讲,使用TCP可能会容易粘包。当然,对接收端的程序来讲,如果机器负荷很重,也会在接收缓冲里粘包(发送端和接收端都有可能发生粘包问题)。
这样,就需要接收端额外拆包,增加了工作量。因此,这个特别适合的是数据要求可靠传输,但是不需要太频繁传输的场合(两次操作间隔100ms,具体是由TCP等待发送间隔决定的,取决于内核中的socket的写法)
UDP为什么没有粘包问题
由于面向的是消息传输,它把所有接收到的消息都挂接到缓冲区的接受队列中,因此,它对于数据的提取分离就更加方便,但是,它没有粘包机制,
因此,当发送数据量较小的时候,就会发生数据包有效载荷较小的情况,也会增加多次发送的系统发送开销(系统调用,写硬件等)和接收开销。
因此,应该最好设置一个比较合适的数据包的包长,来进行UDP数据的发送。(UDP最大载荷为1472,因此最好能每次传输接近这个数的数据量,这特别适合于视频,音频等大块数据的发送,同时,通过减少握手来保证流媒体的实时性)
举个例子:
我们连续发送三个数据包,大小分别是2k, 4k , 8k,这三个数据包,都已经到达了接收端的网络堆栈中,如果使用UDP协议,不管我们使用多大的接收缓冲区去接收数据,我们必须有三次接收动作,才能够把所有的数据包接收完.而使用TCP协议,我们只要把接收的缓冲区大小设置在14k以上,我们就能够一次把所有的 数据包接收下来.只需要有一次接收动作.
这就是因为UDP协议的保护消息边界使得每一个消息都是独立的.而流传输,却把数据当作一串数据流,他不认为数据是一个一个的消息.所以有很多人在使用TCP协议通讯的时候,并不清楚TCP是基于流的传输,当连续发送数据的时候,他们时常会认识tcp会丢包.其实不然, 因为当他们使用的缓冲区足够大时,他们有可能会一次接收到两个甚 至更多的数据包,而很多人往往会忽视这一点,只解析检查了第一个数据包,而已经接收的其他数据包却被忽略了.所以大家如果要作这 类的网络编程的时候,必须要注意这一点.
粘包问题解决方案
TCP粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。
出现粘包现象的原因是多方面的,它既可能由发送方造成,也可能由接收方造成。
简单得说,在流传输中出现,UDP不会出现粘包,因为它有消息边界(参考Windows网络编程)
1发送端需要等缓冲区满才发送出去,造成粘包
2接收方不及时接收缓冲区的包,造成多个包接收
具体点:
(1)发送方引起的粘包是由TCP协议本身造成的,TCP为提高传输效率,发送方往往要收集到足够多的数据后才发送一包数据。若连续几次发送的数据都很少,通常TCP会根据优化算法把这些数据合成一包后一次发送出去,这样接收方就收到了粘包数据。
(2)接收方引起的粘包是由于接收方用户进程不及时接收数据,从而导致粘包现象。这是因为接收方先把收到的数据放在系统接收缓冲区,用户进程从该缓冲区取数据,若下一包数据到达时前一包数据尚未被用户进程取走,则下一包数据放到系统接收缓冲区时就接到前一包数据之后,而用户进程根据预先设定的缓冲区大小从系统接收缓冲区取数据,这样就一次取到了多包数据。
粘包情况有两种,一种是粘在一起的包都是完整的数据包,另一种情况是粘在一起的包有不完整的包。
不是所有的粘包现象都需要处理,若传输的数据为不带结构的连续流数据(如文件传输),则不必把粘连的包分开(简称分包)。但在实际工程应用中,传输的数据一般为带结构的数据,这时就需要做分包处理。
在处理定长结构数据的粘包问题时,分包算法比较简单;在处理不定长结构数据的粘包问题时,分包算法就比较复杂。特别是粘在一起的包有不完整的包的粘包情况,由于一包数据内容被分在了两个连续的接收包中,处理起来难度较大。实际工程应用中应尽量避免出现粘包现象。
一种比较周全的对策是:接收方创建一预处理线程,对接收到的数据包进行预处理,将粘连的包分开。对这种方法我们进行了实验,证明是高效可行的。
具体可以参考:http://blog.csdn.net/soli/article/details/1297109
TCP无保护消息边界的解决
针对这个问题,一般有3种解决方案:
(1)发送固定长度的消息
(2)把消息的尺寸与消息一块发送
(3)使用特殊标记来区分消息间隔
关于Socket粘包、半包问题的解决方法相关推荐
- 三、Netty的粘包半包问题解决
一.定义 TCP 传输中,客户端发送数据,实际是把数据写入到了 TCP 的缓存中,粘包和半包也就会在此时产生.客户端给服务端发送了两条消息ABC和DEF,服务端这边的接收会有多少种情况呢?有可能是一次 ...
- Netty粘包/半包问题解析
目录 一.什么是粘包/半包问题 二.TCP粘包/半包发生的原因 三.粘包/半包解决办法 四.Netty中粘包/半包解决示例 1. 采用固定长度数据包编解码方式 2. 采用特殊字符作为边界字符编解码方式 ...
- 网络:什么是TCP粘包/半包?怎么解决这个问题
在socket网络编程中,都是端到端通信,由客户端端口+服务端端口+客户端IP+服务端IP+传输协议组成的五元组可以明确的标识一条连接.在TCP的socket编程中,发送端和接收端都有成对的socke ...
- TCP 粘包半包 netty 编解码 三者关系
1 何为粘包 / 半包? 对方一次性接收了多条消息这种现象,我们就称之为 粘包现象. 对方多次接收了不完整消息这种现象,我们就称之为 半包现象. 粘包的原因: 发送方发送的消息 < 缓冲区大小 ...
- Netty框架之TCP粘包/半包解决方案
Netty框架之TCP粘包/半包解决方案 一.TCP粘包 二.TCP半包 三.TCP粘包/半包解决方案 1.FixedLengthFrameDecoder定长解析器 2.LineBasedFrameD ...
- Netty如何解决粘包半包问题
何为粘包 / 半包? 比如,我们发送两条消息:ABC 和 DEF,那么对方收到的就一定是 ABC 和 DEF 吗? 不一定,对方可能一次就把两条消息接收完了,即 ABCDEF:也可能分成了好多次,比如 ...
- websocket是否需要处理粘包半包问题分析
结论: 不需要. 背景: 公司通信涉及到websocket相关,我们都知道websocket是基于tcp的,而tcp是面向字节流的,是需要处理粘包半包问题的.那么websocket是否需要处理 ...
- netty——黏包半包的解决方案、滑动窗口的概念
黏包半包 滑动窗口 在深入理解黏包半包问题之前,先了解TCP的一个知识点--滑动窗口 我们都指定tcp是一种可靠的传输协议,这主要是因为在tcp中客户端给服务器端发送一条消息,要等待服务器端的应答,如 ...
- Python 下载依赖包环境经常失败超时解决方法
Python 下载依赖包环境经常失败超时解决方法 参考文章: (1)Python 下载依赖包环境经常失败超时解决方法 (2)https://www.cnblogs.com/boonya/p/11909 ...
- Linux安装软件时缺少依赖包的简单较完美解决方法!
Linux安装软件时缺少依赖包的简单较完美解决方法! 参考文章: (1)Linux安装软件时缺少依赖包的简单较完美解决方法! (2)https://www.cnblogs.com/xiaommvik/ ...
最新文章
- Nginx配置文件nginx.conf中文详解(总结)
- TensorFlow Google大会总结
- YUV视频格式到RGB32格式转换的速度优化 上篇(转)
- SQL Server中查询所有的表、视图、列和存储过程
- PostgreSQL数据目录深度揭秘
- qt中设置QTabWidget,QGroupBox,QScrollArea的样式
- 浅谈python使用多态跟不用多态的区别_python 多态和 super 用法
- 深入理解Hadoop之HDFS架构
- El 表达式、jstl学习
- TypeScript简介
- 强连通分量[trajan]
- 数据库连接池Spring JDBC(JdbcTemplate)
- mpp格式文用什么软件打开
- oracle所有分区表分区,Oracle分区表及分区目录
- 为什么程序员大多数都会脱发?( ConcurrentHashMap 并发)
- 别做正常的傻瓜-读后感
- 酷睿i7 11800h相当于什么水平 i711800h属于哪个档次
- 计算机网络--串行传输与并行传输
- AndroidStudio蓝牙通信
- 什么是附近推?附近推怎么投放?