All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.youyinnn.common.AbstractAioHandler Maven / Gradle / Ivy

The newest version!
package com.github.youyinnn.common;

import com.github.youyinnn.common.packet.BasePacket;
import org.tio.core.ChannelContext;
import org.tio.core.GroupContext;
import org.tio.core.exception.AioDecodeException;
import org.tio.core.intf.AioHandler;
import org.tio.core.intf.Packet;

import java.nio.ByteBuffer;

/**
 * @author youyinnn
 */
public abstract class AbstractAioHandler implements AioHandler {

    /**
     * 解码:把接收到的ByteBuffer,解码成应用可以识别的业务消息包
     * 总的消息结构:消息头 + 消息体
     * 消息头结构:    4个字节,存储消息体的长度
     * 消息体结构:   对象的json串的byte[]
     * @param byteBuffer
     * @param channelContext
     * @return
     * @throws AioDecodeException
     */
    @Override
    public Packet decode(ByteBuffer byteBuffer, ChannelContext channelContext) throws AioDecodeException {
        int readableLength = byteBuffer.limit() - byteBuffer.position();
        //收到的数据不足以组成业务包, 则返回null告诉框架数据不够
        if (readableLength < BasePacket.HEADER_LENGTH) {
            return null;
        }

        //读取消息类型
        int type = byteBuffer.get();
        //读取的消息长度
        int bodyLength = byteBuffer.getInt();

        /*
         * 如果数据不正确 则抛出异常
         * 这里允许bodyLength为0 因为我们发送的心跳检测包是null的body
         */
        if (bodyLength < 0) {
            throw new AioDecodeException("bodyLength [" + bodyLength + "] is not right, remote:" + channelContext.getClientNode());
        }

        //计算本次需要的数据长度
        int neededLength = BasePacket.HEADER_LENGTH + bodyLength;
        //收到的数据是否足够组包
        int isDataEnough = readableLength - neededLength;
        //不够消息长度(剩下的buffer组不了消息体)
        if (isDataEnough < 0) {
            return null;
        } else {
            byte[] dest = null;
            if (bodyLength > 0) {
                //够消息长度, 则组包
                dest = new byte[bodyLength];
                byteBuffer.get(dest);
            }
            return new BasePacket((byte) type, dest);
        }
    }

    /**
     * 编码:  把业务消息编码为课发送的ByteBuffer
     * 总的消息结构:  消息头 + 消息体
     * 消息头结构:   4字节,存储消息体的长度
     * 消息体结构:   对象的json串的byte[]
     *
     * @param packet
     * @param groupContext
     * @param channelContext
     * @return
     */
    @Override
    public ByteBuffer encode(Packet packet, GroupContext groupContext, ChannelContext channelContext) {
        BasePacket basePacket = (BasePacket) packet;
        byte[] body = basePacket.getMsgBody();
        int bodyLen = 0;
        if (body != null) {
            bodyLen = body.length;
        }

        //bytebuffer的总长度 = 消息头长度 + 消息体长度
        int allLen = BasePacket.HEADER_LENGTH + bodyLen;
        //创建一个新的bytebuffer
        ByteBuffer buffer = ByteBuffer.allocate(allLen);
        //设置字节序
        buffer.order(groupContext.getByteOrder());

        //写入消息类型
        buffer.put(basePacket.getMsgType());
        //写入消息体长度
        buffer.putInt(bodyLen);

        //写入消息体
        if (body != null) {
            buffer.put(body);
        }

        return buffer;
    }

    @Override
    public void handler(Packet packet, ChannelContext channelContext) throws Exception {
        handler((BasePacket) packet, channelContext);
    }

    /**
     * 第二层handler:
     * 该方法需要在框架自调用的handler方法里最后调用,
     * 意图统一抽出对应的msgBody对象,紧接着调用第三层handler.
     *
     * @param packet
     * @param channelContext
     * @return
     * @throws Exception
     */
    public abstract Object handler(BasePacket packet, ChannelContext channelContext) throws Exception;
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy