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
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Netty5.0 架构剖析和源码解读 作者:李林锋 版权所有 email neu_lilinfeng@ © Netty5.0 架构剖析和源码解读1 1. 概述2 1.1. JAVA 的IO演进2 1.1.1. 传统BIO通信的弊端2 1.1.2. Linux 的网络IO模型简介4 1.1.3. IO复用技术介绍7 1.1.4. JAVA的异步IO8 1.1.5. 业界主流的NIO框架介绍10 2.NIO入门10 2.1. NIO服务端10 2.2. NIO客户端13 3.Netty源码分析16 3.1. 服务端创建16 3.1.1. 服务端启动辅助类ServerBootstrap16 3.1.2. NioServerSocketChannel 的注册21 3.1.3. 新的客户端接入25 3.2. 客户端创建28 3.2.1. 客户端连接辅助类Bootstrap28 3.2.2. 服务端返回ACK应答,客户端连接成功32 3.3. 读操作33 3.3.1. 异步读取消息33 3.4. 写操作39 3.4.1. 异步消息发送39 3.4.2. Flush操作42 4.Netty架构50 4.1. 逻辑架构50 5. 附录51 5.1. 作者简介51 5.2. 使用声明51 1. 概述 1.1.JAVA 的IO演进 1.1.1. 传统BIO通信的弊端 在JDK 1.4推出JAVANIO1.0之前,基于JAVA 的所有Socket通信都采用 BIO 了同步阻塞模式( ),这种一请求一应答的通信模型简化了上层的应用开发, 但是在可靠性和性能方面存在巨大的弊端。所以,在很长一段时间,大型的应 C C++ 用服务器都采用 或者 开发。当并发访问量增大、响应时间延迟变大后, 采用JAVABIO作为服务端的软件只有通过硬件不断的扩容来满足访问量的激 增,它大大增加了企业的成本,随着集群的膨胀,系统的可维护性也面临巨大 的挑战,解决这个问题已经刻不容缓。 首先,我们通过下面这幅图来看下采用BIO 的服务端通信模型:采用BIO 通信模型的 1connect NewThread1 WebBrowse 2connect 2handle(Req) WebBrowse 3connect Acceptor NewThread2 WebBrowse WebBrowse 4connect NewThread3 3sendResponsetopeer NewThread4 图1.1.1-1 BIO通信模型图 服务端,通常由一个独立的Accepto 线程负责监听客户端的连接,接收到客户 端连接之后为客户端连接创建一个新的线程处理请求消息

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值