TCP是个“流”协议,所谓流,就是没有界限的一串数据。大家可以想象河里的流水,他们是连成一片的,其间并没有分界线。TCP底层并不了解上层业务数据的具体含义,他会根据TCP缓冲区的实际情况进行包的划分,所以在业务上认为,一个完整的包可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送。这就是TCP所谓的拆包和粘包的问题。

一、TCP粘包/拆包问题说明

我们可以通过图解对TCP粘包和拆包问题进行说明,粘包问题如图。

假设客户端分别发送了两个数据包D1和D2给服务端,由于服务端一次读取到的字节数是不确定的,故可能存在以下4中情况。

  • 服务端分两次读取到了两个独立的数据包,分别是D1和D2,没有粘包和拆包。
  • 服务端一次接收到了两个数据包,D1和D2粘在一起,被称为TCP粘包
  • 服务端分两次读取到了两个数据包,第一次读取到了完整的D1包和D2包的部分内容,第二次读取到了D2包的剩余内容,这被称为TCP拆包。
  • 服务端分两次读取到了两个数据包,第一次读取到了D1包的部分内容D1_1,第二次读取到了D1包的剩余内容D1_2和D2包的整包。

如果此时服务端TCP接收滑窗非常小,而数据包D1和D2比较大,很有可能会发生第五种可能,即服务端分多次才能将D1和D2包接收完全,期间发生多次拆包。

二、TCP粘包/拆包发生的原因

问题产生的原因有三个,分别如下。

  • 应用程序write写入的字节大小大于套接口发送缓冲区大小。
  • 进行MSS大小的TCP分段。
  • 以太网帧的payload大于MTU进行IP分片。

三、粘包问题的解决策略

由于底层的TCP无法理解上层的业务数据,所以在底层是无法保证数据包不被拆分和重组的,这个问题只能通过上层的应用协议栈设计来解决,根据业界的主流协议的解决方案,可以归纳如下。

  • 消息定长,例如每个报文的大小为固定长度200字节,如果不够,空位补空格
  • 在包尾增加回车换行符进行分割,例如FTP协议
  • 将消息分为消息头和消息体,消息头中包含表示消息总长度(或者消息体长度)的字段,通常涉及思路为消息头的第一个字段使用int32来表示消息的总长度
  • 更复杂的应用层协议。

Java网络编程基础之TCP粘包拆包的更多相关文章

  1. python网络编程基础之socket粘包现象

    粘包现象两种 登陆 #服务端import json import socket server=socket.socket()#创建socket对象 ip_port=('127.0.0.1',8001) ...

  2. Java网络编程和NIO详解开篇:Java网络编程基础

    Java网络编程和NIO详解开篇:Java网络编程基础 计算机网络编程基础 转自:https://mp.weixin.qq.com/s/XXMz5uAFSsPdg38bth2jAA 我们是幸运的,因为 ...

  3. java网络编程socket\server\TCP笔记(转)

    java网络编程socket\server\TCP笔记(转) 2012-12-14 08:30:04|  分类: Socket |  标签:java  |举报|字号 订阅     1 TCP的开销 a ...

  4. Java网络编程基础(Netty预备知识)

    今天在家休息,闲来无事,写篇博客,陶冶下情操~~~ =================我是分割线================ 最近在重新学习Java网络编程基础,以便后续进行Netty的学习. 整 ...

  5. 用java网络编程中的TCP方式上传文本文件及出现的小问题

    自己今天刚学java网络编程中的TCP传输,要用TCP传输文件时,自己也是遇到了一些问题,抽空把它整理了一下,供自己以后参考使用. 首先在这个程序中,我用一个客户端,一个服务端,从客户端上传一个文本文 ...

  6. TCP粘包/拆包 ByteBuf和channel 如果没有Netty? 传统的多线程服务器,这个也是Apache处理请求的模式

    通俗地讲,Netty 能做什么? - 知乎 https://www.zhihu.com/question/24322387 谢邀.netty是一套在java NIO的基础上封装的便于用户开发网络应用程 ...

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

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

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

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

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

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

随机推荐

  1. (广搜) Find a way -- hdu -- 2612

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=2612 Find a way Time Limit: 3000/1000 MS (Java/Others) ...

  2. ZSTU4270 同源数 2017-03-22 14:34 82人阅读 评论(0) 收藏

    4270: 同源数 Time Limit: 3 Sec  Memory Limit: 128 MB Submit: 1284  Solved: 224 Description 如果x和y的质因子集合完 ...

  3. Charles网络工具

    Charles 是在 Mac 下常用的网络封包截取工具,在做移动开发时,我们为了调试与服务器端的网络通讯协议,常常需要截取网络封包来分析. Charles 通过将自己设置成系统的网络访问代理服务器,使 ...

  4. 浅析互联网系统和传统企业IT系统的异同

    前不久,一则中行宕机的消息引起了网上IT人士的热议.其中对于大型机或者RISC系统的稳定性可靠性的质疑更是热议中的主流声音,很多人拿现在互联网系统做对比,认为大型机所谓的几个9都是吹出来的云云.在这里 ...

  5. 在ASP.NET Core2上操作MongoDB就是能这么的简便酷爽(自动完成分库分表)

    NoSQL是泛指非关系型的数据库,现今在我们的项目中也多有使用,其独特的优点为我们的项目架构带来了不少亮点,而我们这里的主角(MongoDB)则是NoSQL数据库家族中的一种.事实上,NoSQL数据库 ...

  6. Objective-C 学习笔记(四) 数组

    Objective-C 数组作为函数参数传递 如果想在一个函数作为参数,通过一维数组,就必须声明函数形式参数 方式一    指针作为形式参数 - (void) myFunction(int *) pa ...

  7. PG数据库错误: 检测到OA幸运飞艇源码ShareLock死锁处理

    PostgreSQL 是一个免费数据库,OA幸运飞艇源码下载,详情咨询[企娥166848365]对于处理分析型+交易型混合型系统来说确实很不错,特别是版本的升级到11.2后性能提升很多,很多运行机制跟 ...

  8. tomcat启动时就频繁gc和full gc

    一个小业务,流量并不大,功能也很简单,spring framework+mybatis+quartz,一启动就看到gc的频次和full gc的频次非常高: 4.202: [Full GC 4.202: ...

  9. ArcGIS(批量)删除属性字段

    ArcGIS下删除属性字段有两种方式:① 单个删除:② 批量删除. 单个删除 批量删除 尽管如此,ArcGIS桌面软件在属性字段的编辑上并不太方便,所以我们自己做了一些工具辅助平时的内业处理工作.(* ...

  10. Jenkins的多个任务并串联参数传递

    Jenkins的多个任务并串联参数传递 Parameterized Trigger Plugin插件可以使多个job连接的时候可以传递一些job相关的参数信息. 1.Parameterized Tri ...