netty---------write flush两个方法到底做了什么?
上一篇已经看到: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两个方法到底做了什么?的更多相关文章
- substring()方法到底做了什么?不同版本的JDK中是否有区别?为什么?
该文章是图说Java系列文章中的一篇 substring(int beginIndex, int endIndex)方法在jdk 6和jdk 7中的实现是不同的.了解他们的区别可以帮助你更好的使用 ...
- AFNetworking到底做了什么
写在开头: 作为一个iOS开发,也许你不知道NSUrlRequest.不知道NSUrlConnection.也不知道NSURLSession...(说不下去了...怎么会什么都不知道...)但是你一定 ...
- R语言中将hello打印10次的两种方法
我们有两种方法来做这件事情: 1.for结构 for循环重复的执行一个语句,直到某个变量的值不再包含在序列seq中为止. 语法: for (var in seq) statement 例如: > ...
- 在vc6.0下编的对话框界面如果没做过其他处理,往往显的很生硬,怎么样才能使他有Windows XP的风格呢,其实也很简单,我们来看看下面两种方法。
在vc6.0下编的对话框界面如果没做过其他处理,往往显的很生硬,怎么样才能使他有Windows XP的风格呢,其实也很简单,我们来看看下面两种方法. 方法一: 1.首先确认你在Windows ...
- AFNetworking到底做了什么?(二)
接着上一篇的内容往下讲,如果没看过上一篇内容可以点这: AFNetworking到底做了什么? 之前我们讲到NSUrlSession代理这一块: 代理8: /* task完成之后的回调,成功和失败 ...
- CSS-animations和transitions性能:浏览器到底做了什么?
CSS animations 和 transitions 的性能:浏览器到底做了什么?(译) 原文地址:http://blogs.adobe.com/webplatform/2014/03/18/cs ...
- Java中随机数生成的两种方法,以及math的floor
1.Math的random方法,调用这个Math.Random()函数能够返回带正号的double值,该值大于等于0.0且小于1.0,即取值范围是[0.0,1.0)的左闭右开区间,返回值是一个伪随机选 ...
- Linux添加系统调用的两种方法
前言 系统调用的基本原理 系统调用其实就是函数调用,只不过调用的是内核态的函数,但是我们知道,用户态是不能随意调用内核态的函数的,所以采用软中断的方式从用户态陷入到内核态.在内核中通过软中断0X80, ...
- java-IO流-字节流-概述及分类、FileInputStream、FileOutputStream、available()方法、定义小数组、BufferedInputStream、BufferedOutputStream、flush和close方法的区别、流的标准处理异常代码
1.IO流概述及其分类 * 1.概念 * IO流用来处理设备之间的数据传输 * Java对数据的操作是通过流的方式 * Java用于操作流的类都在IO包中 * ...
随机推荐
- Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: ..... this is incompatible with sql_mode=only_full_group_by
一.异常信息 org.springframework.jdbc.BadSqlGrammarException: ### Error querying database. Cause: com.mysq ...
- 图解GIT,ZT
图解GIT,ZT http://nettedfish.sinaapp.com/blog/2013/08/05/deep-into-git-with-diagrams/
- Jquery常用的一些事件 keyup focus
(1)keyup 事件能在用户每次松开按键时触发,实现即时提醒: (2)focus 事件能在元素得到焦点的时候触发,也可以实现即时提醒. (3)为了使表单填写准确,在表单提交之前,需要对表单的必须填写 ...
- stock 基本操作
追涨停 量比 大于5 0%-2% 个股 2点卖 37分钟买 板块5 -8 只涨停 板块分向标 追踪短期个股的涨跌现象 明白市场大级别趋势 主 ...
- Calendar Game HDU - 1079
Adam and Eve enter this year’s ACM International Collegiate Programming Contest. Last night, they pl ...
- vscode插件之C/C++
目录 1.给C/C++调试器配置launch.json 2.配置VS Code的调试行为 3.配置目标应用 4.自定义GDB或者LLDB 5.调试dump(转储)文件 6.远程调试或者本地服务器上调试 ...
- Financiers Game CodeForces - 737D (博弈论)
直接暴力区间DP的话是$O(n^3)$, 关键注意到每步走的距离差不超过1, 所以差最大是$O(\sqrt{n})$的, 所以实际上有用的状态是$O(n^2)$的, 可以通过.
- 2018-2019 ACM-ICPC Brazil Subregional Programming Contest
A:留坑 B:二维sg函数,特判边界情况 //#pragma GCC optimize(2) //#pragma GCC optimize(3) //#pragma GCC optimize(4) / ...
- HDU-2874-森林求LCA/tarjan
http://acm.hdu.edu.cn/showproblem.php?pid=2874 给出一个森林,询问任意两点最短距离. tarjan跑一遍即可,就是这个题卡内存,vector会MLE,换前 ...
- Golang 在 Mac、Linux、Windows 下如何交叉编译(转)
原文地址:Golang 在 Mac.Linux.Windows 下如何交叉编译 Golang 支持交叉编译,在一个平台上生成另一个平台的可执行程序,最近使用了一下,非常好用,这里备忘一下. Mac 下 ...