Mina自动分包、粘包的解决方法

最近用JAVA做服务端,使用Mina框架对接终端设备,通过TCP通讯,在数据量较大的情况下,遇到Mina接收数据不完整的情况,经过研究,找到解决方法,记录如下:

Mina版本:2.1.2

1.实现ProtocolCodecFactory类,用来拦截数据包。


import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFactory;
import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolEncoder;
import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class MessageCodecFactory implements ProtocolCodecFactory {

    @Autowired
    private MinaMessageEncoder encoder;
    @Autowired
    private MinaMessageDecoder decoder;

    @Override
    public ProtocolDecoder getDecoder(IoSession session) throws Exception {
        return decoder;
    }

    @Override
    public ProtocolEncoder getEncoder(IoSession session) throws Exception {
        return encoder;
    }
}

2.再在在chain里面注册编解码器。

@Autowired
private MessageCodecFactory factory;

public static IoAcceptor acceptor;

/**处理数据的服务*/
@Autowired
private MinaServer minaServer;

@Bean
public IoAcceptor ioAcceptor() throws Exception {
    acceptor = new NioSocketAcceptor();
    acceptor.getFilterChain().addLast("logger", new LoggingFilter());
    acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(factory));
    acceptor.getSessionConfig().setMaxReadBufferSize(1024);
    acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 60);
    acceptor.setHandler(minaServer);
    acceptor.bind(new InetSocketAddress(port));
    return acceptor;
    }

3.实现decode和encoder

继承CumulativeProtocolDecoder类实现Decode:

import lombok.extern.slf4j.Slf4j;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import org.springframework.stereotype.Component;

/**
 * mina自动分包粘包的处理
 */
@Slf4j
@Component
public class MinaMessageDecoder extends CumulativeProtocolDecoder {

    @Override
    protected boolean doDecode(IoSession ioSession, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
        /**读取当前 IoBuffer 中已接收到的数据,判断是否得到了完整的数据包*/
        byte[] data = new byte[in.limit()];
        in.get(data);

        /**解析接收到的数据,根据指令约定进行判断数据是否接收完整*/
        String typeStr = ByteUtil.bytesToHexString(data).toLowerCase();
        if (typeStr.startsWith("cc")) {
            byte[] msg = FingerParamHandler.getFingerMsg(data);
            /**msg为空则为数据接收不完整,这里根据自身情况更改判断逻辑,接收不完整,调用in.rewind(),并返回false,*/
            if (msg == null) {
                in.rewind();
                return false;/**通知父类的 decode 方法,当前数据不完整,放弃本次读取,下个数据包到来时再做处理*/
            }
        }
        /**创建一个包含一个完整数据包的IoBuffer对象*/
        IoBuffer buffer = IoBuffer.wrap(data);
        /**将IoBuffer对象写出,在IoHandlerAdapter类的messageReceived方法中进行处理*/
        out.write(buffer);
        return true;/**通知父类的 decode 方法,当前接收并读取的数据已处理*/
    }

}
继承ProtocolEncoderAdapter实现Encode:
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
import org.apache.mina.filter.codec.ProtocolEncoderOutput;
import org.springframework.stereotype.Component;

@Component
public class MinaMessageEncoder extends ProtocolEncoderAdapter {
    /**这里不做处理*/
    @Override
    public void encode(IoSession ioSession, Object message, ProtocolEncoderOutput out) throws Exception {

    }
}

到此,完成Mina自动分包粘包的问题。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值