java Netty处理充电桩报文粘包、拆包方案解决

充电桩硬件发送报文有时多条一起发送,所以在服务器端要拆分包,直接上代码

package com.icojoo.chargeNetty.tcpIp;
import com.icojoo.chargeNetty.utils.BytesUtil;
import com.icojoo.chargeNetty.utils.IcojooUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;
import lombok.extern.slf4j.Slf4j;
import java.net.InetSocketAddress;
import java.util.List;

/**
 * 解码器<br>
 * 解决粘包问题
 * 
 * @author icojoo
 *
 */
@Slf4j
public class MyDecoder extends MessageToMessageDecoder<byte[]> {

    @Override
    protected void decode(ChannelHandlerContext ctx, byte[] msg, List<Object> out) throws Exception {
        try {

            if (IcojooUtil.isYunKuaiChong(msg)) {
                // 云快充
                unpackSH(msg, out);
            }else {
                log.info( " unkown proctrol 未知协议类型" );
                //out.add(msg);
            }

        } catch (Exception e) {
            log.error(" decode Exception : " + e.toString());
        }
    }


    /**
     * 云快充拆包
     */
    private void unpackSH(byte[] msg, List<Object> out) {
        // 获取报文的长度帧,并转化10进制字节,在加上起始帧1个字节+长度帧1个字节+效验帧2个字节,所以+4,
        int len = BytesUtil.toInt2(msg, 1)+4;
        if (msg.length <= len) { // 一个整包
            out.add(msg);

        } else {
            // 1.取出一个包的数据
            byte[] array = new byte[len];
            System.arraycopy(msg, 0, array, 0, len);
            out.add(array);

            // 2. 多余的数据继续分包
            int other = msg.length - len;
            array = new byte[other];
            System.arraycopy(msg, len, array, 0, array.length);
            unpackSH(array, out);

        }

    }


    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
        InetSocketAddress address = (InetSocketAddress) ctx.channel().remoteAddress();
        String ip = address.toString();

        log.info("channelActive -->  RamoteAddress : " + ip + " connected ");
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.error(" exceptionCaught : " + cause.toString() + " ctx = " 
                    + ctx.channel().toString() );
        ctx.close();
    }

}
package com.icojoo.chargeNetty.tcpIp;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.bytes.ByteArrayDecoder;
import io.netty.handler.codec.bytes.ByteArrayEncoder;
import io.netty.handler.timeout.IdleStateHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

@Component
public class ServerChannelInitializer extends ChannelInitializer<SocketChannel> {

    @Autowired
    ServerChannelHandler serverChannelHandler;

    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        ChannelPipeline pipeline = socketChannel.pipeline();
        // 字符串编解码器
        pipeline.addLast("decoder",new ByteArrayDecoder());
        pipeline.addLast("encoder",new ByteArrayEncoder());
        //IdleStateHandler心跳机制,如果超时触发Handle中userEventTrigger()方法
        pipeline.addLast("idleStateHandler", new IdleStateHandler(15,0,0, TimeUnit.MINUTES));
        //拆包这个是重点
        pipeline.addLast(new MyDecoder());
        // 自定义Handler
        pipeline.addLast("serverChannelHandler",serverChannelHandler);
    }
}

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

触角云科技

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值