Netty4客户端使用遇到的坑笔记

1.注意ChannelPipeline中handler的调用顺序。完整的发送与接收过程,是先发送再接收,所以是先执行out再执行in。具体参考https://blog.csdn.net/u014614038/article/details/80487942

2.发送数据转码,通过MessageToByteEncoder,比如我使用的是SMessage格式数据:

public class SDataEncoder extends MessageToByteEncoder<SMessage> {

    @Override
    protected void encode(ChannelHandlerContext channelHandlerContext, SMessage sMessage, ByteBuf byteBuf) throws Exception {
        if (sMessage != null) {
            ByteBuf encoded = channelHandlerContext.alloc().buffer(sMessage.getByteData().length);
            encoded.writeBytes(sMessage.getByteData());
            channelHandlerContext.writeAndFlush(encoded);
            channelHandlerContext.flush();
        }
    }

}

3.接收数据转码,通过ByteToMessageDecoder,比如将字节数据转为我使用的SMessage:

public class SDataDecoder extends ByteToMessageDecoder {

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        try {
            ByteBuf d = in.readBytes(in.readableBytes());
            byte[] bs = new byte[d.readableBytes()];
            d.readBytes(bs);
            if (bs.length>0) {
                SMessage sMessage = new SMessage();
                sMessage.data = bs;
                //获取header
                if (sMessage.hasData() && sMessage.data.length >= SHeader.LENGTH) {
                    byte[] headBs = new byte[SHeader.LENGTH];
                    System.arraycopy(sMessage.data, 0, headBs, 0, headBs.length);
                    sMessage.header = new SHeader();
                    sMessage.header.setData(headBs);
                }

                //获取数据body
                if (sMessage.hasData() && sMessage.data.length > SHeader.LENGTH) {
                    byte[] bodyBs = new byte[sMessage.data.length - SHeader.LENGTH];
                    System.arraycopy(sMessage.data, SHeader.LENGTH, bodyBs, 0, bodyBs.length);
                    sMessage.body = new SBody();
                    sMessage.body.dataByte = bodyBs;
                }           
                out.add(sMessage);
            } else {
                   out.add(d);
            }
        } catch (Exception e) {
            System.out.println("SDataDecoder decode  Exception:" + e.toString());
        }
    }
}

这里记得注意的是,不能直接使用ByteBuf,否则会报Exception:java.lang.UnsupportedOperationException: direct buffer异常,需要通过 in.readBytes(in.readableBytes())复制一个新的ByteBuf然后读取字节数据。

4.发送过程抛出异常,包括自己代码写的不好导致的,最终会回调到ClientDataHandler的channelInactive,如果在这个方法执行了重连,可能会导致不断重连,建议捕捉下,避免代码导致的不断重连(比如心跳发送抛出异常,而你会不断发送心跳包)。

5.ChannelHandler都是异步线程中的中执行的,所以任何回调到主线程使用的方法,最终都应该通过主线程回调,否则会不断自动进行断开重连,比如ClientDataHandler中channelActive监听这个方法然后使用我们的监听器stateListener.onActive()回调,这个stateListener.onActive()应该在主线程执行可以(通过mainHandler)。

 public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
        if (stateListener != null) {
            mainHandler.post(new Runnable() {
                @Override
                public void run() {
                    stateListener.onActive();
                }
            });
        }
    }

转载注明:https://blog.csdn.net/u014614038/article/details/80497785

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值