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包中 * ...
随机推荐
- LeetCode--455--分发饼干
问题描述: 假设你是一位很棒的家长,想要给你的孩子们一些小饼干.但是,每个孩子最多只能给一块饼干.对每个孩子 i ,都有一个胃口值 gi ,这是能让孩子们满足胃口的饼干的最小尺寸:并且每块饼干 j , ...
- 如何理解以太坊ABI - 应用程序二进制接口
很多同学不是很明白以太坊ABI是什么,他的作用是什么,读完本文就明白了. 写在前面 阅读本文前,你应该对以太坊.智能合约有所了解, 如果你还不了解,建议你先看以太坊是什么,也可以观看我们的视频:零基础 ...
- Stark组件 (一)
Stark组件构建 1.启动所有app下的stark.py文件,的配置实现步骤 1.创建一个Django项目crm,并创建 app1 ,app2, stark 三个app 2.在crm 项目的set ...
- 小程序用户openid设置放缓存
wx.setStorageSync('openid', res.data.data.openid),设置 var openid = wx.getStorageSync('openid')获取
- canal入门Demo
关于canal具体的原理,以及应用场景,可以参考开发文档:https://github.com/alibaba/canal 下面给出canal的入门Demo (一)部署canal服务器 可以参考官方文 ...
- 【转】XP系统远程桌面连接2012R2提示:远程计算机需要网络级别身份验证,而您的计算机不支持该验证
一.背景 因对方客户的服务器是内网的,需要操作更新服务器的数据库表信息,因此远程对方客户办公司的电脑远程服务器:但是在远程桌面连接出现问题. 二.错误问题 错误问题:“远程计算机需要网络级别身份验证, ...
- 廖雪峰网站:学习python函数—递归函数(四)
# 在函数内部,可以调用其他函数.如果一个函数在内部调用自身本身,这个函数就是递归函数 # 计算阶乘n! = 1 x 2 x 3 x ... x n,用函数fact(n)表示,可以看出: # fact ...
- python-day72--django实现的cookie/session
COOKIE 与 SESSION 一.概念cookie不属于http协议范围,由于http协议无法保持状态,但实际情况,我们却又需要“保持状态”,因此cookie就是在这样一个场景下诞生.cookie ...
- [LeetCode] 95. Unique Binary Search Trees II(给定一个数字n,返回所有二叉搜索树) ☆☆☆
Unique Binary Search Trees II leetcode java [LeetCode]Unique Binary Search Trees II 异构二叉查找树II Unique ...
- 基于spring的PropertySource类实现配置的动态替换
public class ConfigPropertySource extends PropertySource<Properties> implements PriorityOrdere ...