Netty5 Write和Flush事件处理过程_源码讲解

摘要

摘要 本文讲解Netty5 Write和Flush事件处理过程。write是发送端的一个handler里的一个主动的write行为。当进行write的时候,是没有立即发送到网络上的,是会将数据先缓存到本地的(至于是怎么缓冲的,就是本文的主题)。当netty监听到socket的write事件发生的时候,就是worker线程将缓冲的数据flush到内核缓冲区的时候了。flush的触发以及处理流程也是本文讲解的内容。 注意:write不意味着另一端就会立即接收到数据,要看nio的write事件是否发生,对于netty来说,此时是否会出触发flush,才会影响另一端是否会接受到数据

欢迎大家关注我的微博 http://weibo.com/hotbain 会将发布的开源项目技术贴通过微博通知大家,希望大家能够互勉共进!谢谢!也很希望能够得到大家对我博文的反馈,写出更高质量的文章!!

write处理流程

业务逻辑handler调用context的write方法,将欲发送的数据发送到带发送缓冲区中.
看看write流程的触发代码(就是在一个业务handler中调用一下write方法即可):

public class DiscardServerHandler extends ChannelHandlerAdapter {
   
    @Override
    public void channelRead(final ChannelHandlerContext ctx,final  Object msg) throws Exception {
        ByteBuf bufferBuf =(ByteBuf)msg;
    System.out.println(new String(bufferBuf.array()));
    ctx.channel().write(bufferBuf);
}

追踪一下,ctx.channel().write(bufferBuf)的实现(假设out pipeline中没有其他的encode handler了,),我们会看到,最终会由AbstractUnsafe(AbstractUnsafe是channel的一个内部类对象)的write方法(很好找,顺着找就行了,记住,默认pipeline必定会有tail和head两个handler)进行处理,上代码:

public void write(Object msg, ChannelPromise promise) {
            if (!isActive()) {
                // Mark the write request as failure if the channel is inactive.
                if (isOpen()) {
                    promise.tryFailure(NOT_YET_CONNECTED_EXCEPTION);
                } else {
                    promise.tryFailure(CLOSED_CHANNEL_EXCEPTION);
                }
                // release message now to prevent resource-leak
                ReferenceCountUtil.release(msg);
            } else {
  //往缓存中添加一个消息对象
                outboundBuffer.addMessage(msg, promise);
            }
        }

这里关注一下outboundBuffer.addMessage() 到此处,大家就会恍然大悟,知道怎么回事儿了,就是这样,仅仅将要写入的message object写入到一个buffer中。下面我们来看一下outboundBuffer.addmessage的实现。

注意: outboundBuffer是一个ChannelOutboundBuffer类型的兑现,每一个channel都会一个ChannelOutboundBuffer对象与之关联,用来盛放欲发送的消息.上代码证明一切:

protected abstract class AbstractUnsafe implements Unsafe {
   

        private ChannelOutboundBuffer outboundBuffer = ChannelOutboundBuffer.newInstance(AbstractChannel.this);
        private boolean inFlush0;
}
public abstract class AbstractChannel extends DefaultAttributeMap implements Channel {
   


    private MessageSizeEstimator.Handle estimatorHandle;

    private final Channel parent;
    private final ChannelId id = DefaultChannelId.newInstance();
    private final Unsafe unsafe;//channel中有Unsafe引用
    private final DefaultChannelPipeline pipeline;
    private final ChannelFuture succeededFuture = new SucceededChannelFuture(this, null);
   /**省略部分代码***/
    private final EventLoop eventLoop;

Unsafe对象里有一个outboundBuffer ,而channel里有个unsafe引用,所以可以说,channel与outboundBuffer有has-a关系

看一下ChannelOutboundBuffer outboundBuffer的addMessage实现:

void addMessage(Object msg, ChannelPromise promise) {
        //预测message的size
        int size = channel.estimatorHandle().size(msg);
        if (size < 0) {
            size = 0;
        }
        //创建一个Entry对象,一个entry就是一个欲发送的message以及描述信息
        Entry e = buffer[tail++];
        e.msg = msg;
        e.pendingSize = size;
        e.promise = promise;
        e.total = total(msg); 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值