Netty中的编码器与解码器实现(四)

 Netty中数据通信需要自行根据业务场景抽象出客户端与服务器端通讯协议: 通讯过程中需要进行ByteBuf与JAVA对象中的编解码问题:

直接上代码:

=======================解码器:二进制转换为JAVA对象======================
package org.jy.sso.websocket.stomp.push.netty.chat.system.chatedcode;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;
import lombok.extern.slf4j.Slf4j;
import java.util.List;

/**
 * 数据包解码器: 二进制装换为JAVA对象
 */
@Slf4j
public class PacketDecoder extends MessageToMessageDecoder<ByteBuf> {
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf, List<Object> out) throws Exception {
        out.add(PacketEncodeDecode.INSTANCE.decode(byteBuf));
    }
}
==============================编码器: JAVA对象转换为ByteBuf===========================
package org.jy.sso.websocket.stomp.push.netty.chat.system.chatedcode;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import org.jy.sso.websocket.stomp.push.netty.chat.system.chatprotocol.DataPacket;

/**
 * 数据包编码器: JAVA对象转换为二进制装换
 */
public class PacketEncoder extends MessageToByteEncoder<DataPacket> {
    @Override
    protected void encode(ChannelHandlerContext ctx, DataPacket packet, ByteBuf out) throws Exception {
        PacketEncodeDecode.INSTANCE.encode(out,packet);
    }
}

通讯协议编解码控制器:

package org.jy.sso.websocket.stomp.push.netty.chat.system.chatedcode;

import cn.hutool.core.util.ObjectUtil;
import io.netty.buffer.ByteBuf;
import org.jy.sso.websocket.stomp.push.netty.chat.system.chatcommond.ChatCommand;
import org.jy.sso.websocket.stomp.push.netty.chat.system.chatprotocol.DataPacket;
import org.jy.sso.websocket.stomp.push.netty.chat.system.chatprotocol.request.ChatHeartBeatRequestPacket;
import org.jy.sso.websocket.stomp.push.netty.chat.system.chatprotocol.request.ChatLoginRequestPacket;
import org.jy.sso.websocket.stomp.push.netty.chat.system.chatprotocol.request.ChatMessageRequestPacket;
import org.jy.sso.websocket.stomp.push.netty.chat.system.chatprotocol.response.ChatHeartBeatResponsePacket;
import org.jy.sso.websocket.stomp.push.netty.chat.system.chatprotocol.response.ChatLoginResponsePacket;
import org.jy.sso.websocket.stomp.push.netty.chat.system.chatprotocol.response.ChatMessageResponsePacket;
import org.jy.sso.websocket.stomp.push.netty.chat.system.chatserializer.ChatSerializer;
import org.jy.sso.websocket.stomp.push.netty.chat.system.chatserializer.ChatSerializerType;
import org.jy.sso.websocket.stomp.push.netty.chat.system.chatserializer.impl.ChatIMSerializer;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 通讯协议数据包编解码器
 */
public class PacketEncodeDecode {

    /**
     * 协议魔法值
     */
    public static final int MAGIC_NUMBER = 0x12345678;
    // 单例
    public static final PacketEncodeDecode INSTANCE = new PacketEncodeDecode();
    // 存放指令与对应的请求类,这里的value,对泛型的上线的限定
    private Map<Byte, Class<? extends DataPacket>> packetTypeMap;
    // 系列化接口
    private final Map<Byte, ChatSerializer> serializerMap;

    // 构造函数中初始化化,项目上线后这里一般都基本上不变
    private PacketEncodeDecode() {
        packetTypeMap = new HashMap<>();
        // 线程安全
        packetTypeMap = Collections.synchronizedMap(packetTypeMap);
      

        //心跳检测请求指令
        packetTypeMap.put(ChatCommand.HEARTBEAT_REQUEST_COMMAND, ChatHeartBeatRequestPacket.class);
        // 心跳检测响应指令
        packetTypeMap.put(ChatCommand.HEARTBEAT_RESPONSE_COMMAND, ChatHeartBeatResponsePacket.class);


        // 线程安全
        serializerMap = new ConcurrentHashMap<>();
        ChatSerializer chatMsgSerializer = new ChatIMSerializer();
        // 系列化算法key,对应的实现类
        serializerMap.put(chatMsgSerializer.getSerializerAlgorithm(), chatMsgSerializer);


    }


    /**
     * @param packet 传递的数据协议包
     * @return {@link io.netty.buffer.ByteBuf}}
     * @deprecated 编码封装协议的数据的过程
     */
    public ByteBuf encode(ByteBuf byteBuf, DataPacket packet) {
        // 2.系列化Java对象,java对象要系列化,必须实现Serializer接口,否则返回null
        byte[] bytes = ChatSerializerType.DEFAULT_ALGORITHM_Serializer.serializer(packet);
        // 3.实际编码过程
        byteBuf.writeInt(MAGIC_NUMBER);// 协议魔法值
        byteBuf.writeByte(packet.getVersion()); // 版本号
        byteBuf.writeByte(ChatSerializerType.DEFAULT_ALGORITHM_Serializer.getSerializerAlgorithm()); // 系列化算法
        // 之类实现了该方法
        byteBuf.writeByte(packet.getCommand()); // 指令
        // 数组的长度,在解码的时候取出来
        byteBuf.writeInt(bytes.length);
        byteBuf.writeBytes(bytes);
        return byteBuf;
    }

    /**
     * @param byteBuf 数据包缓存区
     * @return {@link org.jy.sso.websocket.stomp.push.netty.chat.system.chatprotocol.DataPacket}
     * @deprecated 解码, 将二进制封装成对象的过程
     */
    public DataPacket decode(ByteBuf byteBuf) {
        // 跳过魔数
        byteBuf.skipBytes(4);
        // 跳过版本号
        byteBuf.skipBytes(1);
        // 获取系列化算法标识
        byte serializeAlgorithm = byteBuf.readByte();
        // 指令
        byte command = byteBuf.readByte();
        // 数据包的长度
        int packetLength = byteBuf.readInt();
        // 读取客户端传递过来的数据包数组的长度
        byte[] bytes = new byte[packetLength];
        byteBuf.readBytes(bytes);
        Class<? extends DataPacket> chatRequest = matchChatRequestType(command);
        ChatSerializer serializer = matchMsgSerializer(serializeAlgorithm);
        return ObjectUtil.isAllNotEmpty(chatRequest, serializer) ? serializer.deserialize(chatRequest, bytes) : null;
    }

    /**
     * @param serializeAlgorithm 系列化算法标识
     * @return {@link ChatSerializer}
     * @deprecated 根据系列化标识,获取对应的系列化算法
     */
    private ChatSerializer matchMsgSerializer(byte serializeAlgorithm) {
        return serializerMap.get(serializeAlgorithm);
    }

    /**
     * 根据指令获取对应的请求数据包实体
     *
     * @param command 指令
     * @return {@link Class<? extends DataPacket>}
     */
    private Class<? extends DataPacket> matchChatRequestType(byte command) {
        return packetTypeMap.get(command);
    }
}

协议指令集:

package org.jy.sso.websocket.stomp.push.netty.chat.system.chatcommond;

/**
 * 各种指令常量
 */
public interface ChatCommand {
    /**
     * 登录请求指令
     */
    Byte LOGIN_REQUEST_COMMAND = 1;
    /**
     * 登录响应指令
     */
    Byte LOGIN_RESPONSE_COMMAND = 2;
    /**
     * 消息请求指令
     */
    Byte MESSAGE_REQUEST_COMMAND = 3;
    /**
     * 消息响应指令
     */
    Byte MESSAGE_RESPONSE_COMMAND = 4;



    /**
     * 心跳检测请求指令
     */
    Byte HEARTBEAT_REQUEST_COMMAND = 17;

    /**
     * 心跳检测响应指令
     */
    Byte HEARTBEAT_RESPONSE_COMMAND = 18;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值