[编织消息框架][netty源码分析]7 Unsafe 实现类NioSocketChannelUnsafe职责与实现
Unsafe 是channel的内部接口, 负责跟socket底层打交道。从书写跟命名上看是不公开给开发者使用的,直到最后实现NioSocketChannelUnsafe也没有公开出去
public interface Channel extends AttributeMap, ChannelOutboundInvoker, Comparable<Channel> {
interface Unsafe {
RecvByteBufAllocator.Handle recvBufAllocHandle();
SocketAddress localAddress();
SocketAddress remoteAddress();
void register(EventLoop eventLoop, ChannelPromise promise);
void bind(SocketAddress localAddress, ChannelPromise promise);
void connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise);
void disconnect(ChannelPromise promise);
void close(ChannelPromise promise);
void closeForcibly();
void deregister(ChannelPromise promise);
void beginRead();
void write(Object msg, ChannelPromise promise);
void flush();
ChannelPromise voidPromise();
ChannelOutboundBuffer outboundBuffer();
}
public interface NioUnsafe extends Unsafe {
SelectableChannel ch();
void finishConnect();
void read();
void forceFlush();
}
}
NioSocketChannelUnsafe 继承关系为: NioSocketChannelUnsafe -> NioByteUnsafe -> AbstractNioUnsafe -> AbstractUnsafe
AbstractUnsafe:负责socket 链路绑定、接受、关闭,数据fush操作
每个操作大概分四个阶段处理
@Override
public final void bind(final SocketAddress localAddress, final ChannelPromise promise) {
assertEventLoop();
//执行前检查
if (!promise.setUncancellable() || !ensureOpen(promise)) {
return;
} boolean wasActive = isActive();
//调用实现
try {
doBind(localAddress);
} catch (Throwable t) {
safeSetFailure(promise, t);
closeIfClosed();
return;
} //调用业务,通知pipeline
if (!wasActive && isActive()) {
invokeLater(()-> pipeline.fireChannelActive(););
}
//完成阶段处理
safeSetSuccess(promise);
}
@Override
public final void flush() {
assertEventLoop(); ChannelOutboundBuffer outboundBuffer = this.outboundBuffer;
if (outboundBuffer == null) {
return;
} outboundBuffer.addFlush();
flush0();
} @SuppressWarnings("deprecation")
protected void flush0() {
//刚完成Flush操作
if (inFlush0) {
return;
} final ChannelOutboundBuffer outboundBuffer = this.outboundBuffer;
if (outboundBuffer == null || outboundBuffer.isEmpty()) {
return;
} inFlush0 = true; //发送数据前链路检查
if (!isActive()) {
try {
if (isOpen()) {
//true 通知 handler channelWritabilityChanged方法
outboundBuffer.failFlushed(FLUSH0_NOT_YET_CONNECTED_EXCEPTION, true);
} else {
outboundBuffer.failFlushed(FLUSH0_CLOSED_CHANNEL_EXCEPTION, false);
}
} finally {
inFlush0 = false;
}
return;
} try {
//调用channel实现
doWrite(outboundBuffer);
} catch (Throwable t) {
if (t instanceof IOException && config().isAutoClose()) {
close(voidPromise(), t, FLUSH0_CLOSED_CHANNEL_EXCEPTION, false);
} else {
outboundBuffer.failFlushed(t, true);
}
} finally {
inFlush0 = false;
}
}
AbstractNioUnsafe:是NioUnsafe接口模板类,简单的包装
NioByteUnsafe:主要对NioUnsafe接口 read操作实现
NioSocketChannelUnsafe:只是简单的包装,最终公开给内部使用
NioByteUnsafe read方法
public final void read() {
final ChannelConfig config = config();
final ChannelPipeline pipeline = pipeline();
final ByteBufAllocator allocator = config.getAllocator();
final RecvByteBufAllocator.Handle allocHandle = recvBufAllocHandle();
allocHandle.reset(config);
ByteBuf byteBuf = null;
boolean close = false;
try {
do {
byteBuf = allocHandle.allocate(allocator);
//填充byteBuf 调用channel实现
int size = doReadBytes(byteBuf);
//记录最后读取长度
allocHandle.lastBytesRead(size);
//链路关闭,释放byteBuf
if (allocHandle.lastBytesRead() <= 0) {
byteBuf.release();
byteBuf = null;
close = allocHandle.lastBytesRead() < 0;
break;
}
//自增消息读取处理次数
allocHandle.incMessagesRead(1);
//已完成填充byteBuf 调用业务pipeline
readPending = false;
pipeline.fireChannelRead(byteBuf);
byteBuf = null;
} while (allocHandle.continueReading());
allocHandle.readComplete();
pipeline.fireChannelReadComplete();
if (close) {
closeOnRead(pipeline);
}
} catch (Throwable t) {
handleReadException(pipeline, byteBuf, t, close, allocHandle);
} finally {
//如果不是主动read 要完成后要清理read op
if (!readPending && !config.isAutoRead()) {
removeReadOp();
}
}
}
}
小结:可以看出没有任何的计算代码,Unsafe只实现边界检查、流程控制,具体实现交给上层处理
[编织消息框架][netty源码分析]7 Unsafe 实现类NioSocketChannelUnsafe职责与实现的更多相关文章
- [编织消息框架][netty源码分析]6 ChannelPipeline 实现类DefaultChannelPipeline职责与实现
ChannelPipeline 负责channel数据进出处理,如数据编解码等.采用拦截思想设计,经过A handler处理后接着交给next handler ChannelPipeline 并不是直 ...
- [编织消息框架][netty源码分析]4 eventLoop 实现类NioEventLoop职责与实现
NioEventLoop 是jdk nio多路处理实现同修复jdk nio的bug 1.NioEventLoop继承SingleThreadEventLoop 重用单线程处理 2.NioEventLo ...
- [编织消息框架][netty源码分析]11 ByteBuf 实现类UnpooledHeapByteBuf职责与实现
每种ByteBuf都有相应的分配器ByteBufAllocator,类似工厂模式.我们先学习UnpooledHeapByteBuf与其对应的分配器UnpooledByteBufAllocator 如何 ...
- [编织消息框架][netty源码分析]5 eventLoop 实现类NioEventLoopGroup职责与实现
分析NioEventLoopGroup最主有两个疑问 1.next work如何分配NioEventLoop 2.boss group 与child group 是如何协作运行的 从EventLoop ...
- [编织消息框架][netty源码分析]8 Channel 实现类NioSocketChannel职责与实现
Unsafe是托委访问socket,那么Channel是直接提供给开发者使用的 Channel 主要有两个实现 NioServerSocketChannel同NioSocketChannel 致于其它 ...
- [编织消息框架][netty源码分析]9 Promise 实现类DefaultPromise职责与实现
netty Future是基于jdk Future扩展,以监听完成任务触发执行Promise是对Future修改任务数据DefaultPromise是重要的模板类,其它不同类型实现基本是一层简单的包装 ...
- [编织消息框架][netty源码分析]5 EventLoopGroup 实现类NioEventLoopGroup职责与实现
分析NioEventLoopGroup最主有两个疑问 1.next work如何分配NioEventLoop 2.boss group 与child group 是如何协作运行的 从EventLoop ...
- [编织消息框架][netty源码分析]13 ByteBuf 实现类CompositeByteBuf职责与实现
public class CompositeByteBuf extends AbstractReferenceCountedByteBuf implements Iterable<ByteBuf ...
- [编织消息框架][netty源码分析]3 EventLoop 实现类SingleThreadEventLoop职责与实现
eventLoop是基于事件系统机制,主要技术由线程池同队列组成,是由生产/消费者模型设计,那么先搞清楚谁是生产者,消费者内容 SingleThreadEventLoop 实现 public abst ...
随机推荐
- css定位 浮动 伪类 margin
一,margin .标准文档流,margin在竖直方向的不叠加,以较大的为准 .使用margin: auto;的盒子必须有明确的width,并且只有标准文档流的盒子 才能使用margin: auto; ...
- java文件的读写操作
java文件的读写操作主要是对输入流和输出流的操作,由于流的分类很多,所以概念很容易模糊,基于此,对于流的读写操作做一个小结. 1.根据数据的流向来分: 输出流:是用来写数据的,是由程序(内存)--- ...
- 用VsCode编辑TypeScript
文地址:https://code.visualstudio.com/Docs/languages/typescript TypeScript是Javascript的超集,它提供了类.模块.接口来帮助你 ...
- Java中实现String.padLeft和String.padRight
因为习惯了C#中的padLeft和padRight,接触Java后突然失去这两个功能,觉得别扭,就试着实现了这两个方法. Java中String.format()中带有字符串对齐功能如下: Syste ...
- 关于cisco ccp 或sdm管理gns3中思科路由器的成功分享
本来工作环境中有一台c1841,闲来无事,升级了最新的IOS=c1841-adventerprisek9-mz.151-4.M6.bin,在xp虚拟机中安装sdm(新windows系统不支持)和在wi ...
- 更新jar包里的配置文件
更新jar包里的配置文件 起因 从笔记本传了个jar到服务器,运行的时候才发现配置文件一个ip项填错了.本来很简单的问题,maven重新打包就可以了,但是30多M的jar包就因为一个配置项错了又要重新 ...
- poj3067 Japan 树状数组求逆序对
题目链接:http://poj.org/problem?id=3067 题目就是让我们求连线后交点的个数 很容易想到将左端点从小到大排序,如果左端点相同则右端点从小到大排序 那么答案即为逆序对的个数 ...
- 【转】c++ new操作符的重载
基本概念: 1. 操作符重载:C++支持对某个操作符赋予不同的语义 2. new操作符:申请内存,调用构造函数 关于c++ new操作符的重载 你知道c++ 的new 操作符和operator new ...
- 详解CockroachDB事务处理系统
本文提到的一些术语,比如Serializability和Linearizability,解释看Linearizability, Serializability and Strict Serializa ...
- 200 OK (from cache)原因
Meta标签中的http-equiv用来标记不可缓存或过期时间,但效果一般.而且代理缓存基本不访问HTML文档内容,所以尽量少用meta标签控制缓存. Pragma: no-cache Forces ...