参考文献:极客时间傅健老师的《Netty源码剖析与实战》Talk is cheap.show me the code!

  开始之前先介绍下Netty写数据的三种方式:

    ①:write:写到一个buffer,flush:把buffer里的数据发送出去

    ②:writeAndFlush:写到buffer,立马发送

    ③:write和flush之间有个ChannelOutboundBuffer

 可以用生活中快递场景来类比下:

  write相当于揽收到仓库,flush相当于从仓库发货,writeAndFlush相当于揽收到仓库立马就发货(类似加急件),ChannelOutboundBuffer相当于揽收和发货之间有个缓冲的仓库

----主线:如图:

  

----2源码演示:

  在channelRead()加入断点,启动服务端和客户端

开始跟进ctx.write();一直跟下回来到:

然后继续跟进invokeWrte();

然后跟进invokeWrite0();

再继续跟进write(),一步一步则会进入到这:

上图代码执行的地方就相当于发快递的仓库这一步骤;继续往下走则能看到:

可以简单进去看一看:

它是添加到队尾;接着继续下边的“incrementPendingOutboundBytes()”;

判断待发送的数据的size是否高于高水位线,如果高于则修改为不可写状态。然后跳出来,write()完成之后开始发送了:在发送的地方加一个断点:

套路一样:

然后找到flush()

再继续跟进:

addFlush()就表示要装车发货了,跟进看看:

它的意思就是把unflushedEntry里面的数据转Flush里面去。然后跳回去:

进入flush0();

进入doWrite();

挨个走就是调用jdk的实现

----3总结:

  写的本质:

      -single write:sun.nio.ch.SocketChannelImpl#write(java.nio.ByteBuffer)(单个写)

      -gathering write:sun.nio.ch.SocketChannelImpl#write(java.nio.ByteBuffer[],int,int)(批量写)

  写数据写不进去时,会停止写,注册一个OP_WRITE事件,来通知什么时候可以写进去

  OP_WRITE不是说有数据可写,而是说可以写进去,所以正常情况,不能注册,否则一直触发

  批量写数据时,如果尝试写的都写进去了,接下来会尝试写更多(maxBytesPerGatheringWrite)。

  只要有数据要写,且能写,则一直尝试,直到16次(writeSpinCount),写16次还没有写完,就直接schedule一个task来继续写,而不是用注册写事件来触发,更简洁有力。

  待写数据太多,超过一定的水位线(writeBufferWaterMark.high()),会将可写的标志位改成false,让应用端自己做决定要不要继续写。

  channelHandlerContext.channel().write():从TailContext开始执行;  

  channelHandlerContext.write():从当前的Context开始。

我只想做的更好,仅此而已。

Netty源码剖析-发送数据的更多相关文章

  1. Netty源码剖析-接受数据

    参考文献:极客时间傅健老师的<Netty源码剖析与实战>Talk is cheap.show me the code! ----主线:worker thread ①多路复用器(Select ...

  2. Netty 源码剖析之 unSafe.write 方法

    前言 在 Netty 源码剖析之 unSafe.read 方法 一文中,我们研究了 read 方法的实现,这是读取内容到容器,再看看 Netty 是如何将内容从容器输出 Channel 的吧. 1. ...

  3. Netty源码剖析-断开连接

    参考文献:极客时间傅健老师的<Netty源码剖析与实战>Talk is cheap.show me the code! ----主线: ----源码: 在NioEventLoop的unsa ...

  4. Netty源码剖析-业务处理

    参考文献:极客时间傅健老师的<Netty源码剖析与实战>Talk is cheap.show me the code! ----主线:worker thread 触发pipeline.fi ...

  5. Netty源码剖析-启动服务

    参考文献:极客时间傅健老师的<Netty源码剖析与实战>Talk is cheap.show me the code! --1主线分两步: 一:首先在our thread里,如果写在mai ...

  6. Netty源码剖析-关闭服务

    参考文献:极客时间傅健老师的<Netty源码剖析与实战>Talk is cheap.show me the code! ----主线:  ----源码: 先在服务端加个断点和修改下代码:如 ...

  7. Netty源码剖析-构建链接

    参考文献:极客时间傅健老师的<Netty源码剖析与实战>Talk is cheap.show me the code! ----主线: 和启动一样也是有两个线程完成的,boss threa ...

  8. Netty学习笔记(三)——netty源码剖析

    1.Netty启动源码剖析 启动类: public class NettyNioServer { public static void main(String[] args) throws Excep ...

  9. Netty 源码剖析之 unSafe.read 方法

    目录: NioSocketChannel$NioSocketChannelUnsafe 的 read 方法 首先看 ByteBufAllocator 再看 RecvByteBufAllocator.H ...

随机推荐

  1. LibreOJ #119. 最短路

    二次联通门 : LibreOJ #119. 最短路 /* LibreOJ #119. 最短路 堆优化的Dijkstra */ #include <cstring> #include < ...

  2. Vue2 响应式原理

    我们经常用vue的双向绑定,改变data的某个属性值,vue就马上帮我们自动更新视图,下面我们看看原理. Object的响应式原理: 可以看到,其实核心就是把object的所有属性都加上getter. ...

  3. 2019.7.9 校内测试 T1挖地雷

    这一次是交流测试?边交流边测试(滑稽 挖地雷 这个题是一个递推问题. 首先我们看第一个格子,因为它只影响了它的上面和右上面这两个地方是否有雷. 我们可以分3种情况讨论: 1. 第一个格子的数字是2: ...

  4. c 判断字符是否为字母 (iswalpha example)

    #include <stdio.h> #include <wctype.h> int main () { ; wchar_t str[] = L"C++"; ...

  5. 使用Excel拼凑SQL语句

       快速将一列多行数据合并到一个单元格            EXCEL如何快速将一列多行数据合并到一个单元格,并加分隔符?这是批量处理由一线业务员统计的数据时的常用方法,尤其是当一列数据是wher ...

  6. fok函数

    一.fork函数是什么 fork函数将运行着的程序分成2个(几乎)完全一样的进程.如下图: 进程1在进程关系中我们称之为父进程,进程2就是通过fork产生的,我们叫他子进程.这两个进程在fork执行完 ...

  7. java代码连接oracle数据库的方法

    oracle连接数据库的方式和mysql是大同小异的,主要的困难点在于oracle的数据库驱动包和依赖只有官方提供,如果你是用maven添加依赖的话,需要自己从官网下载jar包安装到你本地的maven ...

  8. mysql之group_concat函数

    mysql之group_concat函数 在介绍GROUP_CONCAT之前,我们先来看看concat()函数和concat_ws()函数. 先准备一个测试数据库: mysql> select ...

  9. Linux设备驱动程序 之 per-cpu变量

    数组形式 支持SMP的现代操作系统使用每个cpu上的数据,对于给定的处理器其数据是唯一的:一般来说,每个cpu的数据存放在一个数组中,数组总的每一项对应着系统上的一个存在的处理器:按当前处理器号确定这 ...

  10. keepalived服务

    集群相关概念简述 HA是High Available缩写,是双机集群系统简称,指高可用性集群,是保证业务连续性的有效解决方案,一般有两个或两个以上的节点,且分为活动节点及备用节点. 1.集群的分类: ...