netty中的发送有序与channel使用

简单写一个示例代码:

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println(msg.toString());
        t = msg;
        ctx.write(msg);
       ctx.fireChannelRead(msg);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        // TODO Auto-generated method stub
        ctx.flush();
        super.channelReadComplete(ctx);
    }

这个代码在ctx.fireChannelRead(msg);的时候,最终会调用到tail的inboundhandle。tail inboundhandle是netty默认的最后一个处理

msg的handle。将msg进行realse。那么当 ctx.flush();的时候,msg已经被释放掉,再读取msg,就会报错。

所以如果直接写 ctx.write(msg);复用msg的时候,坚决不能释放msg的引用。那么msg的引用什么时间会被释放呢?

当flush调用成功后,真正写入channel以后,DefaultChannelPipeline$HeadContext,最终会调用ChannelOutboundBuffer的

remove方法,将已经写入的内容从待写的链表中删除。

    public boolean remove() {
        Entry e = flushedEntry;
        if (e == null) {
            clearNioBuffers();
            return false;
        }
        Object msg = e.msg;

        ChannelPromise promise = e.promise;
        int size = e.pendingSize;

        removeEntry(e);

        if (!e.cancelled) {
            // only release message, notify and decrement if it was not canceled before.
            ReferenceCountUtil.safeRelease(msg);
            safeSuccess(promise);
            decrementPendingOutboundBytes(size, false, true);
        }

        // recycle the entry
        e.recycle();

        return true;
    }

在ReferenceCountUtil.safeRelease(msg);会删除掉msg的引用。释放msg。

总之,在tail的inboundhandle会free掉msg。而head的outboundhandle会在写入channel后,free掉msg。

如果需要在inbound中回写msg。可以参见《netty 实战》的2.3.1的写法。

注意如下写法也会报错:

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println(msg.toString());
        t = msg;
        ctx.writeAndFlush(msg);
       ctx.fireChannelRead(msg);
    }

这是因为ctx.writeAndFlush(msg)执行成功后(真正写入到channel中,因为writeandflush可能尝试16次依然无法写入成功

会放入到队列中下次继续写),msg会被释放。当ctx.firechannelRead到tail handle时,会因为msg的引用已经为0,而报错。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值