tcp是一个“流”的协议,一个完整的包可能会被TCP拆分成多个包进行发送,也可能把小的封装成一个大的数据包发送,这就是所谓的TCP粘包和拆包问题。

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

  • 1.服务端分2次读取到了两个独立的包,分别是D1,D2,没有粘包和拆包;
  • 2.服务端一次性接收了两个包,D1和D2粘在一起了,被成为TCP粘包;
  • 3.服务端分2次读取到了两个数据包,第一次读取到了完整的D1和D2包的部分内容,第二次读取到了D2包的剩余内容,这被称为拆包;
  • 4.服务端分2次读取到了两个数据包,第一次读取到了部分D1,第二次读取D1剩余的部分和完整的D2包;
  • 5.如果此时服务端TCP接收滑动窗非常小,而数据包D1和D2都很大,很有可能发送第五种可能,即服务端多次才能把D1和D2接收完全,期间多次发生拆包情况。

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

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

Netty对以上4种应用做了抽象,提供了4种解码器

LineBasedFrameDecoder:依次编译bytebuf中的可读字符,判断看是否有“\n”或者“\r\n”,如果有,就以此位置为结束位置,从可读索引到结束位置区间的字节就组成了一行。它是以换行符为结束标志的解码器,支持携带结束符或者不携带结束符两种解码方式,同时支持单行的最大长度。如果连续读取到最大长度后,仍然没有发现换行符,就会抛出异常,同时忽略掉之前读到的异常码流。

FixedLengthFrameDecoder:是固定长度解码器,它能按照指定的长度对消息进行自动解码,开发者不需要考虑TCP的粘包等问题。利用FixedLengthFrameDecoder解码,无论一次性接收到多少的数据,他都会按照构造函数中设置的长度进行解码;如果是半包消息,FixedLengthFrameDecoder会缓存半包消息并等待下一个包,到达后进行拼包,直到读取完整的包。

DelimiterBasedFrameDecoder:是自定义的分隔符解码,构造函数的第一个参数表示单个消息的最大长度,当达到该长度后仍然没有查到分隔符,就抛出TooLongFrameException异常,防止由于异常码流缺失分隔符导致的内存溢出。

LengthFieldBasedFrameDecoder:通过固定长度来区分整包消息。消息定长,报文大小固定长度,不够空格补全,发送和接收方遵循相同的约定,这样即使粘包了通过接收方编程实现获取定长报文也能区分。

netty的解码器与粘包和拆包的更多相关文章

  1. netty的解码器和粘包拆包

    Tcp是一个流的协议,一个完整的包可能会被Tcp拆成多个包进行发送,也可能把一个小的包封装成一个大的数据包发送,这就是所谓的粘包和拆包问题 粘包.拆包出现的原因: 在流传输中出现,UDP不会出现粘包, ...

  2. Netty学习(四)-TCP粘包和拆包

    我们都知道TCP是基于字节流的传输协议.那么数据在通信层传播其实就像河水一样并没有明显的分界线,而数据具体表示什么意思什么地方有句号什么地方有分号这个对于TCP底层来说并不清楚.应用层向TCP层发送用 ...

  3. netty 解决TCP粘包与拆包问题(一)

    1.什么是TCP粘包与拆包 首先TCP是一个"流"协议,犹如河中水一样连成一片,没有严格的分界线.当我们在发送数据的时候就会出现多发送与少发送问题,也就是TCP粘包与拆包.得不到我 ...

  4. 【Netty】TCP粘包和拆包

    一.前言 前面已经基本上讲解完了Netty的主要内容,现在来学习Netty中的一些可能存在的问题,如TCP粘包和拆包. 二.粘包和拆包 对于TCP协议而言,当底层发送消息和接受消息时,都需要考虑TCP ...

  5. Netty入门系列(2) --使用Netty解决粘包和拆包问题

    前言 上一篇我们介绍了如果使用Netty来开发一个简单的服务端和客户端,接下来我们来讨论如何使用解码器来解决TCP的粘包和拆包问题 TCP为什么会粘包/拆包 我们知道,TCP是以一种流的方式来进行网络 ...

  6. Netty(4)Stream by codec(粘包与拆包)

    TCP/IP,传输的是byte[],将byte[]放入队列中.可能会发生粘包和拆包. 比如,客户端向服务端发送了2条消息,分别为D1,D2,可能产生的情况,如下图所示: 情况一:正常的. 情况二:粘包 ...

  7. Netty中粘包和拆包的解决方案

    粘包和拆包是TCP网络编程中不可避免的,无论是服务端还是客户端,当我们读取或者发送消息的时候,都需要考虑TCP底层的粘包/拆包机制. TCP粘包和拆包 TCP是个“流”协议,所谓流,就是没有界限的一串 ...

  8. Netty—TCP的粘包和拆包问题

    一.前言 虽然TCP协议是可靠性传输协议,但是对于TCP长连接而言,对于消息发送仍然可能会发生粘贴的情形.主要是因为TCP是一种二进制流的传输协议,它会根据TCP缓冲对包进行划分.有可能将一个大数据包 ...

  9. 粘包和拆包及Netty解决方案

    在RPC框架中,粘包和拆包问题是必须解决一个问题,因为RPC框架中,各个微服务相互之间都是维系了一个TCP长连接,比如dubbo就是一个全双工的长连接.由于微服务往对方发送信息的时候,所有的请求都是使 ...

随机推荐

  1. json_decode() expects parameter 1 to be string, object given

    $data = Weann\Socialite\Facades\Socialite::driver('wechat')->user();//是字符串 $data=json_encode($dat ...

  2. python_matplotlib知识点总结

    文作为学习过程中对matplotlib一些常用知识点的整理,方便查找. 强烈推荐ipython无论你工作在什么项目上,IPython都是值得推荐的.利用ipython --pylab,可以进入PyLa ...

  3. strcpy、strncpy、memcpy的区别

    一.strcpy.strncpy区别 struct gpInfo { char gpcode[9]; char gpName[50]; }; string gpstr = "SZ000001 ...

  4. 用C结构体来实现面向对象编程,ti xDAIS标准算法就这么搞的(1)

    用C结构体来实现面向对象编程,ti xDAIS标准算法就这么搞的. 测试代码如下: #include <stdio.h> #include <stdlib.h> #includ ...

  5. linux -- ubuntu 脚本开机自启动

    有一个脚本想在ubuntu 虚拟机开机时,自动运行. 创建脚本文件 在“/opt/lampp/”下新建一个脚本文件:lampp_start.sh #!/bin/bash /opt/lampp/lamp ...

  6. CentOS服务器上搭建Gitlab安装步骤、中文汉化详细步骤、日常管理以及异常故障排查

    一, 服务器快速搭建gitlab方法 可以参考gitlab中文社区 的教程centos7安装gitlab:https://www.gitlab.cc/downloads/#centos7centos6 ...

  7. MongoDB基础入门视频教程

    MongoDB基础入门视频教程http://www.icoolxue.com/album/show/98

  8. c++ ++i and i++

    ++i 在 i 存储的值上增加一并向使用它的表达式 ``返回" 新的, 增加后的值; 而 i++ 对 i 增加一, 但返回原来的是未增加的值. 至于++i和i++有什么区别,举个例子 1.a ...

  9. sudo 之后 unable to resolve host的问题解决办法

    gedit /etc/hosts #127.0.0.1 localhost #127.0.0.1 Masterback或者其他 把后面的Masterback 或者其他改成新的主机名,应该是最近修改过主 ...

  10. 【PyMongo】连接10055错误的处理--windows7

    http://stackoverflow.com/questions/25621893/mongodump-utility-raise-socketexception