自定义协议(RPC)

本文介绍了在IT技术中处理粘包问题的四种策略,包括使用固定长度、特殊字符分隔、自定义协议以及在发送和接收时的逻辑判断,如区分心跳请求与普通请求并正确编码和解码数据。
摘要由CSDN通过智能技术生成

解决粘包问题的几种方式

1、固定长度的信息

2、以特殊字符作为边界

3、自定义协议

0    1    2    3    4    5    6    7    8    9    10   11   12   13   14   15   16   17   18   19   20   21   22
*   +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
*   |    magic       |ver |headr len|    full length    | type | ser|comp|              RequestId                |time
*   +-----+-----+-------+----+----+----+----+-----------+----- ---+--------+----+----+----+----+----+----+---+---+
*   |                                                                                                             |
*   |                                         body                                                                |
*   |                                                                                                             |
*   +--------------------------------------------------------------------------------------------------------+----------------+

4个字节的魔术值  1个字节的版本号 2个字节的首部长度 4个字节的报文总长度 1个字节的请求类型 1个字节的序列化方式 1个字节的压缩方式 8个字节的请求id 8个字节的请求时间 + 若干请求体

请求类型有两种 一种是心跳请求 请求头为空 一种是其他请求 请求头不为空 所以请求总长度需要先判断类型 再进行计算

封装请求

        // 4个字节的魔数值
        byteBuf.writeBytes(MessageFormatConstant.MAGIC);
        // 1个字节的版本号
        byteBuf.writeByte(MessageFormatConstant.VERSION);
        // 2个字节的头部的长度
        byteBuf.writeShort(MessageFormatConstant.HEADER_LENGTH);
        //总长度不知道 因为body不确定
        //保存当前位置
        fullLengthIndex = byteBuf.writerIndex();
        //先往后移动4个字节
        byteBuf.writerIndex(byteBuf.writerIndex() +         MessageFormatConstant.FULL_FIELD_LENGTH);
        //请求类型
        byteBuf.writeByte(rpcRequest.getRequestType());
        //序列化方式
        byteBuf.writeByte(rpcRequest.getSerializeType());
        //压缩类型
        byteBuf.writeByte(rpcRequest.getCompressType());
        // 8字节的请求id
        byteBuf.writeLong(rpcRequest.getRequestId());
        //请求时间
        byteBuf.writeLong(rpcRequest.getTimeStamp());

判断是否是心跳请求

 // 心跳请求 正常请求 不正常请求
        if(rpcRequest.getRequestType() == RequestTypeEnum.HEARTBEAT_CHECK.getId() ){
            // 处理一下总长度,其实总长度 = header长度
            currentIndex = byteBuf.writerIndex();
            byteBuf.writerIndex(MessageFormatConstant.FULL_FIELD_INDEX);
            byteBuf.writeInt(MessageFormatConstant.HEADER_LENGTH);
            byteBuf.writerIndex(currentIndex);
            if (log.isDebugEnabled()) {
                log.debug("客户端已编码心跳检测");
            }
            return;
        }

正常类型

   //body
        byte[] body = null;
        if (rpcRequest.getRequestPayload() != null) {
            // 根据配置的方式进行序列化
            Serializer serializer = SerializerFactory.getSerializer(rpcRequest.getSerializeType()).getImpl();
            body = serializer.serialize(rpcRequest.getRequestPayload());
            // 根据配置的方式进行压缩
            Compressor compressor = CompressorFactory.getCompressor(rpcRequest.getCompressType()).getImpl();
            body = compressor.compress(body);
        }
        if (body != null){
            byteBuf.writeBytes(body);
            bodyLength = body.length;
        }

        //保存当前位置
        currentIndex = byteBuf.writerIndex();
        byteBuf.writerIndex(fullLengthIndex);
        byteBuf.writeInt(MessageFormatConstant.HEADER_LENGTH + bodyLength);
        //归位
        byteBuf.writerIndex(currentIndex);

        if (log.isDebugEnabled()) {
            log.debug("正常请求{{}]已经完成报文的编码。", rpcRequest.getRequestId());
        }

接收方 以长度帧解码器 解码请求 具体如何使用 可以看这篇博客 写的很好 链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值