上一篇已经看到:netty的读,是调用unsafe的read方法,把channel中的数据read到byteBuff中的byteBuffer里,也是封装了nio的读。

那么根据猜想,netty的写应该也是调用nio 的 channel的write(byteBuffer),将用户空间的数据,写到内核空间。而且nio的write方法对应的netty应该是flush方法,看看是不是这样。

@Override
-----------ChannelHandlerContext的write方法其实是调用的pipeline的write方法,到最后调用的是tail的write方法,
public final ChannelFuture write(Object msg) {
return tail.write(msg);
}
--------------------这里根据传入的boolean值,决定是write还是writeAndflush,先看write
private void write(Object msg, boolean flush, ChannelPromise promise) {
-----------------因为这里执行的是tail的write方法, 所以要看tail的findContextOutbound的逻辑,tail这个context在初始化的时候inbound是true,但是outbound属性是false,所以要从tail往前,找outboundHandler,而head的outbound属性是true的,看它的write方
法,调用的是unsafe的write方法,是AbstractChannel的write方法。看下一段
AbstractChannelHandlerContext next = findContextOutbound();
final Object m = pipeline.touch(msg, next);
EventExecutor executor = next.executor();
if (executor.inEventLoop()) {
if (flush) {
next.invokeWriteAndFlush(m, promise);
} else {
next.invokeWrite(m, promise);
}
} else {
AbstractWriteTask task;
if (flush) {
task = WriteAndFlushTask.newInstance(next, m, promise);
} else {
task = WriteTask.newInstance(next, m, promise);
}
safeExecute(executor, task, promise, m);
}
}
@Override
-----------------unsafe的write方法
public final void write(Object msg, ChannelPromise promise) {
assertEventLoop();
----------------ChannelOutboundBuffer这个类,维护这一个由他自己的内部类entry组成的一个单链表,entry有着指向byteBuffer和byteBuffer数组的指针,本方法的最下面的addMessage,就是新建一个entry,然后放到链表里,ChannelOutboundBuffer自己有三个属性:
----------------flushedEntry :指向第一个已经被flush的entry
----------------unflushedEntry :指向第一个没有被flush的entry
----------------tailEntry : 队尾的指针。这三个其实很简单
ChannelOutboundBuffer outboundBuffer = this.outboundBuffer;
if (outboundBuffer == null) {
safeSetFailure(promise, WRITE_CLOSED_CHANNEL_EXCEPTION);
ReferenceCountUtil.release(msg);
return;
}
int size;
try {
msg = filterOutboundMessage(msg);
size = pipeline.estimatorHandle().size(msg);
if (size < 0) {
size = 0;
}
} catch (Throwable t) {
safeSetFailure(promise, t);
ReferenceCountUtil.release(msg);
return;
}
outboundBuffer.addMessage(msg, size, promise);
}

所以可以看到,所谓的netty的channelHandlerContext的write方法,其实并不是向内核写入数据,而是把msg放入一个链表中,等待flush,而flush方法也是在headContext中,调用的unsafe的flush方法,

注意这里的unsafe是

@Override
public final void flush() {
assertEventLoop();
ChannelOutboundBuffer outboundBuffer = this.outboundBuffer;
if (outboundBuffer == null) {
return;
}
------------这个方法是把flushedEntry指针置空,把unFlushedEntry指针放到队列头部
outboundBuffer.addFlush();
------------下文
flush0();
}
@Override
-----------------从flush0到这一步的逻辑比较复杂,涉及到各种判断,简单起见,直接看这一步NioSocketChannel的doWriteBytes方法,netty的写,对应的是buf的readBytes,这其实只是方法名字取的问题。回忆之前的doReadBytes对应的是buf的writeBytes方法,
当时是把channel的数据读到nio的ByteBuffer中,现在应该是把byteBuffer中的数据write到channel中了,写到内核
protected int doWriteBytes(ByteBuf buf) throws Exception {
final int expectedWrittenBytes = buf.readableBytes();
return buf.readBytes(javaChannel(), expectedWrittenBytes);
}
---------------还是找到之前的那个byteBuf的实现类,可以看出,还是调用nio的socketChannel的write方法,把tmpBuf(一个Nio的ByteBuffer)写到channel中。
private int getBytes(int index, GatheringByteChannel out, int length, boolean internal) throws IOException {
ensureAccessible();
if (length == 0) {
return 0;
} ByteBuffer tmpBuf;
if (internal) {
tmpBuf = internalNioBuffer();
} else {
tmpBuf = buffer.duplicate();
}
tmpBuf.clear().position(index).limit(index + length);
return out.write(tmpBuf);
}

netty---------write flush两个方法到底做了什么?的更多相关文章

  1. substring()方法到底做了什么?不同版本的JDK中是否有区别?为什么?

      该文章是图说Java系列文章中的一篇 substring(int beginIndex, int endIndex)方法在jdk 6和jdk 7中的实现是不同的.了解他们的区别可以帮助你更好的使用 ...

  2. AFNetworking到底做了什么

    写在开头: 作为一个iOS开发,也许你不知道NSUrlRequest.不知道NSUrlConnection.也不知道NSURLSession...(说不下去了...怎么会什么都不知道...)但是你一定 ...

  3. R语言中将hello打印10次的两种方法

    我们有两种方法来做这件事情: 1.for结构 for循环重复的执行一个语句,直到某个变量的值不再包含在序列seq中为止. 语法: for (var in seq) statement 例如: > ...

  4. 在vc6.0下编的对话框界面如果没做过其他处理,往往显的很生硬,怎么样才能使他有Windows XP的风格呢,其实也很简单,我们来看看下面两种方法。

    在vc6.0下编的对话框界面如果没做过其他处理,往往显的很生硬,怎么样才能使他有Windows XP的风格呢,其实也很简单,我们来看看下面两种方法.    方法一: 1.首先确认你在Windows   ...

  5. AFNetworking到底做了什么?(二)

      接着上一篇的内容往下讲,如果没看过上一篇内容可以点这: AFNetworking到底做了什么? 之前我们讲到NSUrlSession代理这一块: 代理8: /* task完成之后的回调,成功和失败 ...

  6. CSS-animations和transitions性能:浏览器到底做了什么?

    CSS animations 和 transitions 的性能:浏览器到底做了什么?(译) 原文地址:http://blogs.adobe.com/webplatform/2014/03/18/cs ...

  7. Java中随机数生成的两种方法,以及math的floor

    1.Math的random方法,调用这个Math.Random()函数能够返回带正号的double值,该值大于等于0.0且小于1.0,即取值范围是[0.0,1.0)的左闭右开区间,返回值是一个伪随机选 ...

  8. Linux添加系统调用的两种方法

    前言 系统调用的基本原理 系统调用其实就是函数调用,只不过调用的是内核态的函数,但是我们知道,用户态是不能随意调用内核态的函数的,所以采用软中断的方式从用户态陷入到内核态.在内核中通过软中断0X80, ...

  9. java-IO流-字节流-概述及分类、FileInputStream、FileOutputStream、available()方法、定义小数组、BufferedInputStream、BufferedOutputStream、flush和close方法的区别、流的标准处理异常代码

    1.IO流概述及其分类 * 1.概念      * IO流用来处理设备之间的数据传输      * Java对数据的操作是通过流的方式      * Java用于操作流的类都在IO包中      *  ...

随机推荐

  1. hdu-2421 Deciphering Password 数学姿势

    给定A,B,对于A^B的每一个因子,M为其因子的因子数的三次方求和. 容易推导得出A^B的每一个因子都是A的质因子的组合(质因子可重复利用),其因子数自然等于所使用的每个质因子的数量乘积. 假设A由质 ...

  2. VS Code设置中文插件

    Vscode是一款开源的跨平台编辑器.默认情况下,vscode使用的语言为英文(en) 1)打开vscode工具: 2)使用快捷键组合[Ctrl+Shift+p],在搜索框中输入“configure ...

  3. php字符串 统计个数

    方法一 $arr=str_split($str); $arr=array_count_values($arr); /* * 方法二 * */ $arr = str_split($str); $a2 = ...

  4. python基础之生成器,生成器函数,列表推导式

    内容梗概: 1. 生成器和生成器函数. 2. 列表推导式. 1.生成器函数1.1 生成器函数. 就是把return换成yield def gen(): print("爽歪歪") y ...

  5. 2015-2016 ACM-ICPC, NEERC, Moscow Subregional Contest J - Jealousy

    题意:有n张照片,每张照片上有一些妹子,要按照片顺序给妹纸安排男朋友,如果妹纸i安排的男朋友之前有女朋友,那么费用+wi,求总费用最小,和输出路径 题解:费用流,先把照片天数建点i连i+1,流量k(最 ...

  6. python-day97--git协同开发

    1.协同开发流程 - 在dev的基础上创建三个开发的分支 -每个人都在自己的分支中进行开发 -第一个人开发完成之后把review分支从云端版本库中拉下来 -将个人的分支与review分支合并(确保re ...

  7. leetcode-algorithms-12 Integer to Roman

    leetcode-algorithms-12 Integer to Roman Roman numerals are represented by seven different symbols: I ...

  8. 【LeetCode】字符串匹配

    给定目标串 haystack 和模式串 needle ,返回 needle 在 haystack 中第一次出现的位置下标,若 needle 不是 haystack 的子串则返回 -1. 1. Brut ...

  9. [Codeforces Round #340 (Div. 2)]

    [Codeforces Round #340 (Div. 2)] vp了一场cf..(打不了深夜的场啊!!) A.Elephant 水题,直接贪心,能用5步走5步. B.Chocolate 乘法原理计 ...

  10. 十八、Spring框架(AOP)

    一.AOP(基于XML方式配置AOP) AOP(Aspect Oriented Program):面向切面编程.思想是:把功能分为核心业务功能和周边功能. 所谓核心业务功能:比如登录,增删改数据都叫做 ...