zoukankan      html  css  js  c++  java
  • netty之bytebuf粘包、分包

    之前开发一款上位机软件就被这个问题困扰的够呛,原因是因为当时我完全不知道还存在这样的问题,直到后来用了数据监控软件才发现了我那些参差不齐的数据包,又结合了之前在网上检索过的文章,最终才了解到了原来还有这么一回事。

    所以,这次学netty的时候特意留了个心眼,提前搜索了一下netty是否也存在粘包这类问题,答案是存在!行吧,那就研究一下怎么解决吧。以下内容来自于笔者自学以及根据个人历史经验总结而成,暂时没在企业项目中处理过相关问题,不保证正确

    首先,我自定义了一个非常简单的解码器,其实并不具备解码功能,目的就是为了证实我的一个猜测:

    public class DecodeHandler extends ByteToMessageDecoder {
        @Override
        protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
            System.out.println(byteBuf.writerIndex());
        }
    }

    在解码器中,输出的是写索引的位置。

    然后,我开始尝试触发解码器,发现当我不断向byteBuf中写入内容后,写索引也不断增长,我写入两字节,写索引就增大2,写入三字节,写索引就增加3。由此,我猜测每次接收数据准备进行解码的bytebuf都是同一个!而不是新建的bytebuf!

    然后,就要根据实际情况来分析了,也就是要看数据的具体格式来分析。比如我之前遇到的那种返回值,是一个定长数组,没有固定的开头标识,除了依靠长度来解析我实在是想不出怎么解析。

    但是,还有一种情况,数据是有开头标识的,比如每个数据包都以0x23,0x23来作为起始值。那么可以先找到数据的起始值在哪里。

    private void find(ByteBuf buf) {
            int count = buf.readableBytes();
            for (int index = buf.readerIndex(); index < count - 2; index++) {
                if (buf.getByte(index) == 0x23 & buf.getByte(index + 1) == 0x23) {
                    buf.readerIndex(index);
                    return;
                }
            }
            buf.readerIndex(count - 1);
        }

    比如可以这样找,或者也可以根据你的实际情况选择是否直接跳过开头标识。

    然后,确定了读索引的位置就比较好办了,接下来的解析方式就看数据的具体格式了,在解析之前有必要检测一下数据长度是否完整,如果不完整,可以选择跳过这一波解析,等待数据接收完整再解析(记得要将读索引恢复到正确的位置)。

  • 相关阅读:
    apt update ,apt upgrade 和 apt dist-upgrade 的区别
    CVE-2018-8639 简单利用 win7
    如何拆解性能测试需求
    博客搬家啦
    驱动开发学习一
    驱动开发基础之数据结构
    c++容器加迭代器和python装饰器的对比
    c++简单学习
    windows下z3安装
    switch反汇编
  • 原文地址:https://www.cnblogs.com/wxdmw/p/13476029.html
Copyright © 2011-2022 走看看