130 lines
4.9 KiB
Markdown
130 lines
4.9 KiB
Markdown
# 精尽 Netty 源码解析 —— Channel(六)之 writeAndFlush 操作
|
||
|
||
# 1. 概述
|
||
|
||
本文接 [《精尽 Netty 源码解析 —— Channel(五)之 flush 操作》](http://svip.iocoder.cn/Netty/Channel-5-flush/) ,分享 Netty Channel 的 `#writeAndFlush(Object msg, ...)` 方法,write + flush 的组合,将数据写到内存队列后,立即刷新**内存队列**,又将其中的数据写入到对端。
|
||
|
||
😈 本来是不准备写这篇的,因为内容主要是 [《精尽 Netty 源码解析 —— Channel(四)之 write 操作》](http://svip.iocoder.cn/Netty/Channel-4-write/) 和 [《精尽 Netty 源码解析 —— Channel(五)之 flush 操作》](http://svip.iocoder.cn/Netty/Channel-5-flush/) 的组合。但是,考虑到内容的完整性,于是乎就稍微水更下下。
|
||
|
||
# 2. AbstractChannel
|
||
|
||
AbstractChannel 对 `#writeAndFlush(Object msg, ...)` 方法的实现,代码如下:
|
||
|
||
```
|
||
@Override
|
||
public ChannelFuture writeAndFlush(Object msg) {
|
||
return pipeline.writeAndFlush(msg);
|
||
}
|
||
|
||
@Override
|
||
public ChannelFuture writeAndFlush(Object msg, ChannelPromise promise) {
|
||
return pipeline.writeAndFlush(msg, promise);
|
||
}
|
||
```
|
||
|
||
- 在方法内部,会调用对应的
|
||
|
||
|
||
|
||
```
|
||
ChannelPipeline#write(Object msg, ...)
|
||
```
|
||
|
||
|
||
|
||
方法,将 write 和 flush
|
||
|
||
|
||
|
||
两个
|
||
|
||
事件在 pipeline 上传播。详细解析,见
|
||
|
||
|
||
|
||
「3. DefaultChannelPipeline」
|
||
|
||
|
||
|
||
。
|
||
|
||
- 最终会传播 write 事件到 `head` 节点,将数据写入到内存队列中。详细解析,见 [「5. HeadContext」](https://svip.iocoder.cn/Netty/Channel-6-writeAndFlush/#) 。
|
||
- 最终会传播 flush 事件到 `head` 节点,刷新**内存队列**,将其中的数据写入到对端。详细解析,见 [「5. HeadContext」](https://svip.iocoder.cn/Netty/Channel-6-writeAndFlush/#) 。
|
||
|
||
# 3. DefaultChannelPipeline
|
||
|
||
`DefaultChannelPipeline#writeAndFlush(Object msg, ...)` 方法,代码如下:
|
||
|
||
```
|
||
@Override
|
||
public final ChannelFuture write(Object msg) {
|
||
return tail.writeAndFlush(msg);
|
||
}
|
||
|
||
@Override
|
||
public final ChannelFuture write(Object msg, ChannelPromise promise) {
|
||
return tail.writeAndFlush(msg, promise);
|
||
}
|
||
```
|
||
|
||
- 在方法内部,会调用 `TailContext#writeAndFlush(Object msg, ...)` 方法,将 write 和 flush **两个**事件在 pipeline 中,从尾节点向头节点传播。详细解析,见 [「4. TailContext」](https://svip.iocoder.cn/Netty/Channel-6-writeAndFlush/#) 。
|
||
|
||
# 4. TailContext
|
||
|
||
TailContext 对 `TailContext#writeAndFlush(Object msg, ...)` 方法的实现,是从 AbstractChannelHandlerContext 抽象类继承,代码如下:
|
||
|
||
```
|
||
@Override
|
||
public ChannelFuture writeAndFlush(Object msg, ChannelPromise promise) {
|
||
if (msg == null) {
|
||
throw new NullPointerException("msg");
|
||
}
|
||
|
||
// 判断是否为合法的 Promise 对象
|
||
if (isNotValidPromise(promise, true)) {
|
||
// 释放消息( 数据 )相关的资源
|
||
ReferenceCountUtil.release(msg);
|
||
// cancelled
|
||
return promise;
|
||
}
|
||
|
||
// 写入消息( 数据 )到内存队列
|
||
write(msg, true, promise); // <1>
|
||
|
||
return promise;
|
||
}
|
||
```
|
||
|
||
- 这个方法,和我们在 [《精尽 Netty 源码解析 —— Channel(四)之 write 操作》](http://svip.iocoder.cn/Netty/Channel-4-write/) 的 [「4. TailContext」](https://svip.iocoder.cn/Netty/Channel-6-writeAndFlush/#) 的小节,`TailContext#write(Object msg, ...)` 方法,基本类似,差异在于 `<1>` 处,调用 `#write(Object msg, boolean flush, ChannelPromise promise)` 方法,传入的 `flush = true` 方法参数,表示 write 操作的同时,**后续**需要执行 flush 操作。代码如下:
|
||
|
||
```
|
||
private void write(Object msg, boolean flush, ChannelPromise promise) {
|
||
// 获得下一个 Outbound 节点
|
||
AbstractChannelHandlerContext next = findContextOutbound();
|
||
// 简化代码 😈
|
||
// 执行 write + flush 操作
|
||
next.invokeWriteAndFlush(m, promise);
|
||
}
|
||
|
||
private void invokeWriteAndFlush(Object msg, ChannelPromise promise) {
|
||
if (invokeHandler()) {
|
||
// 执行 write 事件到下一个节点
|
||
invokeWrite0(msg, promise);
|
||
// 执行 flush 事件到下一个节点
|
||
invokeFlush0();
|
||
} else {
|
||
writeAndFlush(msg, promise);
|
||
}
|
||
}
|
||
```
|
||
|
||
- 在后面,就是 [《精尽 Netty 源码解析 —— Channel(四)之 write 操作》](http://svip.iocoder.cn/Netty/Channel-4-write/) 的 [「5. HeadContext」](https://svip.iocoder.cn/Netty/Channel-6-writeAndFlush/#) 的小节及其后续的小节。
|
||
- 再在后面,就是 [《精尽 Netty 源码解析 —— Channel(五)之 flush 操作》](http://svip.iocoder.cn/Netty/Channel-5-flush/) 。
|
||
|
||
# 666. 彩蛋
|
||
|
||
😈 真的是水更,哈哈哈哈。
|
||
|
||
推荐阅读文章:
|
||
|
||
- 闪电侠 [《netty 源码分析之 writeAndFlush 全解析》](https://www.jianshu.com/p/feaeaab2ce56) 的 [「writeAndFlush: 写队列并刷新」](https://svip.iocoder.cn/Netty/Channel-6-writeAndFlush/#) 小节。 |