在进行Java NIO学习时,发现,如果客户端连续不断的向服务端发送数据包时,服务端接收的数据会出现两个数据包粘在一起的情况,这就是TCP协议中经常会遇到的粘包以及拆包的问题。
我们都知道TCP属于传输层的协议,传输层除了有TCP协议外还有UDP协议。那么UDP是否会发生粘包或拆包的现象呢?答案是不会。UDP是基于报文发送的,从UDP的帧结构可以看出,在UDP首部采用了16bit来指示UDP数据报文的长度,因此在应用层能很好的将不同的数据报文区分开,从而避免粘包和拆包的问题。而TCP是基于字节流的,虽然应用层和TCP传输层之间的数据交互是大小不等的数据块,但是TCP把这些数据块仅仅看成一连串无结构的字节流,没有边界;另外从TCP的帧结构也可以看出,在TCP的首部没有表示数据长度的字段,基于上面两点,在使用TCP传输数据时,才有粘包或者拆包现象发生的可能。
粘包、拆包表现形式
现在假设客户端向服务端连续发送了两个数据包,用packet1和packet2来表示,那么服务端收到的数据可以分为三种,现列举如下:
第一种情况,接收端正常收到两个数据包,即没有发生拆包和粘包的现象,此种情况不在本文的讨论范围内。

第二种情况,接收端只收到一个数据包,由于TCP是不会出现丢包的,所以这一个数据包中包含了发送端发送的两个数据包的信息,这种现象即为粘包。这种情况由于接收端不知道这两个数据包的界限,所以对于接收端来说很难处理。

第三种情况,这种情况有两种表现形式,如下图。接收端收到了两个数据包,但是这两个数据包要么是不完整的,要么就是多出来一块,这种情况即发生了拆包和粘包。这两种情况如果不加特殊处理,对于接收端同样是不好处理的。

粘包、拆包发生原因
发生TCP粘包或拆包有很多原因,现列出常见的几点,可能不全面,欢迎补充,
1、要发送的数据大于TCP发送缓冲区剩余空间大小,将会发生拆包。
2、待发送数据大于MSS(最大报文长度),TCP在传输前将进行拆包。
3、要发送的数据小于TCP发送缓冲区的大小,TCP将多次写入缓冲区的数据一次发送出去,将会发生粘包。
4、接收数据端的应用层没有及时读取接收缓冲区中的数据,将发生粘包。
等等。
粘包、拆包解决办法
通过以上分析,我们清楚了粘包或拆包发生的原因,那么如何解决这个问题呢?解决问题的关键在于如何给每个数据包添加边界信息,常用的方法有如下几个:
1、发送端给每个数据包添加包首部,首部中应该至少包含数据包的长度,这样接收端在接收到数据后,通过读取包首部的长度字段,便知道每一个数据包的实际长度了。
2、发送端将每个数据包封装为固定长度(不够的可以通过补0填充),这样接收端每次从接收缓冲区中读取固定长度的数据就自然而然的把每个数据包拆分开来。
3、可以在数据包之间设置边界,如添加特殊符号,这样,接收端通过这个边界就可以将不同的数据包拆分开。
等等。

原文:https://blog.csdn.net/wxy941011/article/details/80428470

详细:https://blog.csdn.net/zhangxinrun/article/details/6721495

  https://blog.csdn.net/tiandijun/article/details/41961785

TCP粘包,拆包及解决方法的更多相关文章

  1. 第四章 TCP粘包/拆包问题的解决之道---4.1---

    4.1 TCP粘包/拆包 TCP是一个“流”协议,所谓流,就是没有界限的一串数据.TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包的划分,所以在业务上认为,一个完整的包可 ...

  2. Netty使用LineBasedFrameDecoder解决TCP粘包/拆包

    TCP粘包/拆包 TCP是个”流”协议,所谓流,就是没有界限的一串数据.TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包的划分,所以在业务上认为,一个完整的包可能会被TC ...

  3. 《精通并发与Netty》学习笔记(13 - 解决TCP粘包拆包(一)概念及实例演示)

    一.粘包/拆包概念 TCP是一个“流”协议,所谓流,就是没有界限的一长串二进制数据.TCP作为传输层协议并不不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行数据包的划分,所以在业务上认 ...

  4. TCP粘包/拆包问题的解决

    TCP粘包拆包问题 一个完整的包可能被TCP拆分成多个包,或多个小包封装成一个大的数据包发送. 解决策略 消息定长,如果不够,空位补空格 在包尾增加回车换行符进行分割,例如FTP协议 将消息分为消息头 ...

  5. 网络编程——TCP协议、UDP协议、socket套接字、粘包问题以及解决方法

    网络编程--TCP协议.UDP协议.socket套接字.粘包问题以及解决方法 TCP协议(流式协议) ​ 当应用程序想通过TCP协议实现远程通信时,彼此之间必须先建立双向通信通道,基于该双向通道实现数 ...

  6. 深入学习Netty(5)——Netty是如何解决TCP粘包/拆包问题的?

    前言 学习Netty避免不了要去了解TCP粘包/拆包问题,熟悉各个编解码器是如何解决TCP粘包/拆包问题的,同时需要知道TCP粘包/拆包问题是怎么产生的. 在此博文前,可以先学习了解前几篇博文: 深入 ...

  7. Netty(三)TCP粘包拆包处理

    tcp是一个“流”的协议,一个完整的包可能会被TCP拆分成多个包进行发送,也可能把小的封装成一个大的数据包发送,这就是所谓的TCP粘包和拆包问题. 粘包.拆包问题说明 假设客户端分别发送数据包D1和D ...

  8. Netty(二)——TCP粘包/拆包

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/7814644.html 前面讲到:Netty(一)--Netty入门程序 主要内容: TCP粘包/拆包的基础知 ...

  9. TCP粘包/拆包问题

    无论是服务端还是客户端,当我们读取或者发送消息的时候,都需要考虑TCP底层的粘包/拆包机制. TCP粘包/拆包 TCP是个"流"协议,所谓流,就是没有界限的一串数据.大家可以想想河 ...

  10. TCP 粘包/拆包问题

    简介    TCP 是一个’流’协议,所谓流,就是没有界限的一串数据. 大家可以想想河里的流水,是连成一片的.期间并没有分界线, TCP 底层并不了解上层业务数据的具体含义 ,它会根据 TCP 缓冲区 ...

随机推荐

  1. MYSQL CASCADE DELETE 引发的思考

    MYSQL CASCADE DELETE :级联删除.这个概念还是学习Oracle时得到的. 就是主键记录删除时,相关的有外键的表里的记录,也删除. https://dev.mysql.com/doc ...

  2. C++拷贝构造函数的调用时机

    一.拷贝构造函数调用的时机 ​ 当以拷贝的方式初始化对象时会调用拷贝构造函数,这里需要注意两个关键点,分别是以拷贝的方式和初始化对象 1. 初始化对象 初始化对象是指,为对象分配内存后第一次向内存中填 ...

  3. Spring 入门知识点笔记整理

    一.Spring 概述 1. 什么是spring? Spring 是个java企业级应用的开源开发框架.Spring主要用来开发Java应用,但是有些扩展是针对构建J2EE平台的web应用.Sprin ...

  4. hadoop集群故障排除

    故障一:某个datanode节点无法启动 我是以用户名centos安装和搭建了一个测试用的hadoop集群环境,也配置好了有关的权限,所有者.所属组都配成centos:centos [故障现象] 名称 ...

  5. html 文档类型

    <!doctype>用来声明html的版本,浏览器只有知道html的版本后才能正确显示文档,<!DOCTYPE>本身不是一个标签,而是一个声明.

  6. timescale 时间尺度

    1 `timescale为模块指定参考时间单位 `timescale<reference_time_unit>/<time_precision> 2 module endmou ...

  7. 一个死循环导致的栈溢出实例:StackOverFlowError

    有一个功能,要用复选框组做成单选框效果,如果有三个复选框 CheckBox ,并且保证每次只能选中一个.刚开始添加了以下的值改变后的监听方法 addValueChangeListener ,却导致了栈 ...

  8. hihoCoder#1743:K-偏差排列(矩阵快速幂+状压dp)

    题意 如果一个 \(1\to N\) 的排列 \(P=[P_1, P_2, ... P_N]\) 中的任意元素 \(P_i\) 都满足 \(|P_i-i| ≤ K\) ,我们就称 \(P\) 是 \( ...

  9. 【Luogu4931】情侣?给我烧了! 加强版(组合计数)

    [Luogu4931]情侣?给我烧了! 加强版(组合计数) 题面 洛谷 题解 戳这里 忽然发现我自己推的方法是做这题的,也许后面写的那个才是做原题的QwQ. #include<iostream& ...

  10. 【LG 4831】Scarlet loves WenHuaKe(生成函数)

    题目链接 一道好题,第一次用生成函数做题.感谢赛珂狼教我这个做法. 首先我们显然可以把题目中的限制转化成一个二分图的模型:左边有$n$个点,右边有$m$个点,如果在棋盘$(i,j)$这个点上放了炮,那 ...