netty 源码分析

2 篇文章 0 订阅
2 篇文章 0 订阅

netty中的write方法

io.netty.channel.Channel write方法

在这里插入图片描述

//注意这个chnnel是netty中的chinnel,不是nio中的channel
io.netty.channel.Channel
    /**
     * Request to write a message via this {@link Channel} through the {@link ChannelPipeline}.
     * This method will not request to actual flush, so be sure to call {@link #flush()}
     * once you want to request to flush all pending data to the actual transport.
     * 请求通过ChannelPipeline由Channel写消息。 此方法不会请求不会flush,因此一旦您要请求将所有待处理数据刷新到实际传输,请务必调用flush()。
     */
    ChannelFuture write(Object msg);
    
    /**
     * Shortcut for call {@link #write(Object)} and {@link #flush()}.
     */
    ChannelFuture writeAndFlush(Object msg);

//AbstractChannel 类
//由此可知 channel.write()方法实际上是调用的ChannelPipeline的write方法
    @Override
    public ChannelFuture write(Object msg) {
        return pipeline.write(msg);
    }
io.netty.channel.ChannelPipeline

在这里插入图片描述

ChannelFuture
  • The result of an asynchronous Channel I/O operation.(异步channel I/O操作的结果)

    可以判断是否完成 isDone(), 是否成功 isSuccess()等
    可以添加监听器 addListener 当操作完成后执行监听器

为什么netty的写是异步的呢? 返回给你一个ChannelFuture
  • 在java nio中 channel.write (buffer);

Java NIO (中文版) 书中Channel 的 read( ) 和 write( )方法使用 ByteBuffer 对象作为参数。两种方法均返回已传输的字节数,可能比缓冲区的字节数少甚至可能为零

这就是说,我们在write的时候不一定能写入数据.比如说socket的另一端阻塞了,就写不了数据了.
调用nio Channel 的 write就一直会返回0.

所以在netty中,我们写入的东西都会存在一个地方,把 <要写入的东西,ChannelFuture >绑定起来,
要写入的东西 完全被写入后,ChannelFuture就会被设为success,如果有监听器的话,会执行用户写的监听器.

netty中存放<要写入的东西,ChannelFuture >的是ChannelOutboundBuffer类
AbstractChannel 类
//AbstractChannel 类
        @Override
        //把<要写入的东西,ChannelFuture> 关联起来
        public final void write(Object msg, ChannelPromise promise) {
            ChannelOutboundBuffer outboundBuffer = this.outboundBuffer;
            if (outboundBuffer == null) {
                // If the outboundBuffer is null we know the channel was closed and so
                // need to fail the future right away. If it is not null the handling of the rest
                // will be done in flush0()
                // See https://github.com/netty/netty/issues/2362
                safeSetFailure(promise, CLOSED_CHANNEL_EXCEPTION);
                // release message now to prevent resource-leak
                ReferenceCountUtil.release(msg);
                return;
            }
            //把<要写入的东西,ChannelFuture> 关联起来
             outboundBuffer.addMessage(msg, size, promise);

ChannelOutboundBuffer 类
 * (传输实现者) AbstractChannel使用的一个内部的结构来  存储它的待发送请求
 * 所有方法都必须由I / O线程的传输实现调用,但以下方法除外:
 * size()和isEmpty()
 *
 */
public final class ChannelOutboundBuffer {

    //java nio 写了多少个字节,你就来这里面找 已经写入的 **要写入的东西**
    //并调用ChannelFuture的 setSuccess方法
    public void removeBytes(long writtenBytes) {
        for (;;) {
            Object msg = current();
            if (!(msg instanceof ByteBuf)) {
                assert writtenBytes == 0;
                break;
            }

            final ByteBuf buf = (ByteBuf) msg;
            final int readerIndex = buf.readerIndex();
            final int readableBytes = buf.writerIndex() - readerIndex;

            if (readableBytes <= writtenBytes) {
                if (writtenBytes != 0) {
                    progress(readableBytes);
                    writtenBytes -= readableBytes;
                }
                 //把写入完成的  **要写入的东西** ChannelFuture设置为成功
                remove();

    //把写入完成的  **要写入的东西** ChannelFuture设置为成功
    private static void safeSuccess(ChannelPromise promise) {
        if (!(promise instanceof VoidChannelPromise) && !promise.trySuccess()) {
            logger.warn("Failed to mark a promise as success because it is done already: {}", promise);
        }
    }
后记
  • 需要探索的地方
    1. ChannelOutboundBuffer 里面没有被写出的字节不能太大了,在写的时候如果发现这个ChannelOutboundBuffer 太大了,可以停止去写.学习具体API
  • 注意 ChannelFuture的监听器,不能太耗时,也不能死锁,因为它毕竟是在I/O线程里面被调用的.
    验证具体API
  • 如果ChannelFuture
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值