粘包和分包出现的原因是:没有一个稳定数据结构

解决办法: 分割符

     长度 + 数据

* <pre>  
* 数据包格式
* +——----——+——-----——+——----——+——----——+——-----——+
* | 包头 | 模块号 | 命令号 | 长度 | 数据 |
* +——----——+——-----——+——----——+——----——+——-----——+
* </pre>
* 包头4字节
* 模块号2字节short
* 命令号2字节short
* 长度4字节(描述数据部分字节长度)

创建encoder  和 decoder  分别 加入pipeline 中

  1. public class RpcDecoder extends ByteToMessageDecoder {
  2.  
  3. private Class<?> genericClass;
  4.  
  5. public RpcDecoder(Class<?> genericClass) {
  6. this.genericClass = genericClass;
  7. }
  8.  
  9. @Override
  10. public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
  11. if (in.readableBytes() < 4) {
  12. return;
  13. }
  14. in.markReaderIndex();
  15. int dataLength = in.readInt();
  16. if (dataLength < 0) {
  17. ctx.close();
  18. }
  19. if (in.readableBytes() < dataLength) {
  20. in.resetReaderIndex();
  21. return;
  22. }
  23. byte[] data = new byte[dataLength];
  24. in.readBytes(data);
  25.  
  26. Object obj = SerializationUtil.deserialize(data, genericClass);
  27. out.add(obj);
  28. }
  29. }
  1. public class RpcEncoder extends MessageToByteEncoder {
  2.  
  3. private Class<?> genericClass;
  4.  
  5. public RpcEncoder(Class<?> genericClass) {
  6. this.genericClass = genericClass;
  7. }
  8.  
  9. @Override
  10. public void encode(ChannelHandlerContext ctx, Object in, ByteBuf out) throws Exception {
  11. if (genericClass.isInstance(in)) {
  12. byte[] data = SerializationUtil.serialize(in);
  13. out.writeInt(data.length);
  14. out.writeBytes(data);
  15. }
  16. }
  17. }
  1. protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
  2. if (in.readableBytes() >= BASE_LENGTH) {
  3.  
  4. //防止socket字节流攻击
  5. if (in.readableBytes() > 2048) {
  6. in.skipBytes(in.readableBytes());
  7. }
  8.  
  9. //记录包头开始的index
  10. int beginReader;
  11.  
  12. //读取包头
  13. while (true) {
  14. beginReader = in.readerIndex();
  15. in.markReaderIndex();
  16. if (in.readInt() == Constantvalue.FLAG) {
  17. break;
  18. }
  19.  
  20. //未读到包头, 略过一个字节
  21. in.resetReaderIndex();
  22. in.readByte();
  23.  
  24. //长度又变得不满足
  25. if (in.readableBytes() < BASE_LENGTH) {
  26. return;
  27. }
  28. }
  29. }
  30.  
  31. // 模块号
  32. short module = in.readShort();
  33. //命令好
  34. short cmd = in.readShort();
  35. // 长度
  36. int dataLength = in.readInt();
  37.  
  38. if (in.readableBytes() < dataLength) {
  39. //还原读指针
  40. in.resetReaderIndex();
  41. return;
  42. }
  43. byte[] data = new byte[dataLength];
  44. in.readBytes(data);
  45. Request request = new Request();
  46. request.setModule(module);
  47. request.setCmd(cmd);
  48. request.setData(data);
  49. //继续往下传递
  50. out.add(request);
  51.  
  52. }

buffer里面数据未被读取完怎么办

  1. protected void callDecode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
  2. try {
  3. while (in.isReadable()) {
  4. int outSize = out.size();
  5. int oldInputLength = in.readableBytes();
  6. decode(ctx, in, out);
  7.  
  8. // Check if this handler was removed before continuing the loop.
  9. // If it was removed, it is not safe to continue to operate on the buffer.
  10. //
  11. // See https://github.com/netty/netty/issues/1664
  12. if (ctx.isRemoved()) {
  13. break;
  14. }
  15.  
  16. if (outSize == out.size()) { // 这里会对照长度 先判断读到东西了没有, 没有跳出
  17. if (oldInputLength == in.readableBytes()) { // 读取位置变化没
  18. break;
  19. } else {
  20. continue;
  21. }
  22. }
  23.  
  24. if (oldInputLength == in.readableBytes()) {
  25. throw new DecoderException(
  26. StringUtil.simpleClassName(getClass()) +
  27. ".decode() did not read anything but decoded a message.");
  28. }
  29.  
  30. if (isSingleDecode()) {
  31. break;
  32. }
  33. }

数据缓存在 cumulation中

  1. public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
  2. if (msg instanceof ByteBuf) {
  3. RecyclableArrayList out = RecyclableArrayList.newInstance();
  4. try {
  5. ByteBuf data = (ByteBuf) msg;
  6. first = cumulation == null; //第一次请求 cumulation 为 null true
  7. if (first) {
  8. cumulation = data;
  9. } else {
  10. cumulation = cumulator.cumulate(ctx.alloc(), cumulation, data); // 第二次请求时进入 将新的信息追加到cumulation后面
  11. }
  12. callDecode(ctx, cumulation, out);
  13. } catch (DecoderException e) {
  14. throw e;
  15. } catch (Throwable t) {
  16. throw new DecoderException(t);
  17. } finally {
  18. if (cumulation != null && !cumulation.isReadable()) {
  19. cumulation.release();
  20. cumulation = null;
  21. }
  22. int size = out.size();
  23.  
  24. for (int i = 0; i < size; i ++) {
  25. ctx.fireChannelRead(out.get(i));
  26. }
  27. out.recycle();
  28. }
  29. } else {
  30. ctx.fireChannelRead(msg);
  31. }
  32. }

Netty自定义数据包协议的更多相关文章

  1. 基于Netty的RPC架构学习笔记(十):自定义数据包协议

    文章目录 数据包简介 粘包.分包现象 数据包格式 举个

  2. IM通信协议逆向分析、Wireshark自定义数据包格式解析插件编程学习

    相关学习资料 http://hi.baidu.com/hucyuansheng/item/bf2bfddefd1ee70ad68ed04d http://en.wikipedia.org/wiki/I ...

  3. 在dubbo的一端,看Netty处理数据包,揭网络传输原理

    如今,我们想要开发一个网络应用,那是相当地方便.不过就是引入一个框架,然后设置些参数,然后写写业务代码就搞定了. 写业务代码自然很重要,但是你知道: 你的数据是怎么来的吗?通过网络传输过来的呗. 你知 ...

  4. WebSocket数据包协议详解

    其实我一直想不明白HTML5包装个应用层办议作为Socket通过基础目的是为了什么,其实直接支持Socket tcp相对来说更加简单灵活.既然标准已经制定而浏览器也支持那对于我们开发者来说只能用的分. ...

  5. 【求助】NdisSend,自定义数据包发送失败?

    做ndis hook的时候,自定义了一个数据包,包结构应该没有问题,填充NDIS_PACKET结构是这样的,先初始化:        NdisAllocatePacketPool(&nStat ...

  6. TCP/IP网络编程之数据包协议

    一.概要 在了解了网络字节序之后,接下来就是要讲最最重点的消息协议.数据包是什么呢,数据包可以理解为两个人讲电话说的每一句话的内容.通过大家约定好的方式去理解.达到只有接听电话两个人才懂的东西.在程序 ...

  7. asp.net core中遇到需要自定义数据包解密方法的时候

    最近将公司的项目用.netcore重写, 服务的http外部接口部分收发消息是DES加解密的, 那么在asp.net core mvc的action处理之前需要加入解密这个步骤. 我第一想到的是用fi ...

  8. 示例:Netty 处理 TCP数据分包协议

    一个.Netty解决TCP协议的数据分包的想法 我们知道通过TCP协议发送接收数据时,假设数据过大.接收到的数据会是分包的.比方:                                   ...

  9. 如何实现自定义sk_buff数据包并提交协议栈

    目录 一.自定义数据包的封装流程 1. 分配skb 2.初始定位(skb_reserve) 3.拷贝数据(skb_push / skb_pull / skb_put / ) 4.设置传输层头部 5.设 ...

随机推荐

  1. 学习C/C++的简单方法

    如何学习C++呢.C和C++是很多专业的必修课,尤其对计算机专业来说,更是重中之重.C++语言是早期发展的高级语言,具备执行速度快,语法优美等特点.是底层高效率系统的首选开发语言.今天就和大家分享一下 ...

  2. Python Tinker学习笔记

    一直在简单看看python,这次项目需要做个界面,最好是要跨平台的,之前考虑QT,但是树莓派上QT跨平台编译一直装这有问题,后来发现Python不就可以么? 于是决定用python做个界面,但是做界面 ...

  3. windows下安装redis、celery,并启动测试

    Windows 环境下基于 Redis 的 Celery 任务调度模块的实现 搭建环境: Windows-x64 10 Celery 3.1.23 Celery-with-redis 3.0 Redi ...

  4. meshing-球体网格划分

    原视频下载地址:https://yunpan.cn/cqwvgQQ2xy3G6  访问密码 a54b

  5. js的一些兼容性易错的的问题

    一.属性相关 我们通常把特征(attribute)和属性(property)统称为属性,但是他们确实是不同的概念,特征(attribute)会表现在HTML文本中,对特征的修改一定会表现在元素的out ...

  6. 网络爬虫requests-bs4-re-1

    最近了解了爬虫,嗯--------,有时候会搞得有点头晕. 跟着线上老师实现了两个实例.可以用python下载源代码玩玩,爬淘宝的很刺激,虽然违反了ROBOTS协议. GIT地址

  7. BaggingClassifier

      写在前面 Ensemble methods 组合模型的方式大致为四个:/bagging / boosting / voting / stacking ,此文主要简单叙述 bagging算法. 算法 ...

  8. GCC编译流程及常用编辑命令

    GCC 编译器在编译一个C语言程序时需要经过以下 4 步: 将C语言源程序预处理,生成.i文件. 预处理后的.i文件编译成为汇编语言,生成.s文件. 将汇编语言文件经过汇编,生成目标文件.o文件. 将 ...

  9. OpenGL ES: (3) EGL、EGL绘图的基本步骤、EGLSurface、ANativeWindow

    1. EGL概述 EGL 是 OpenGL ES 渲染 API 和本地窗口系统(native platform window system)之间的一个中间接口层,它主要由系统制造商实现. EGL提供如 ...

  10. keras Model 1 入门篇

    1 入门 2 多个输入和输出 3 共享层 最近在学习keras,它有一些实现好的特征提取的模型:resNet.vgg.而且是带权重的.用来做特诊提取比较方便 首先要知道keras有两种定义模型的方式: ...