[编织消息框架][netty源码分析]8 Channel 实现类NioSocketChannel职责与实现
Unsafe是托委访问socket,那么Channel是直接提供给开发者使用的
Channel 主要有两个实现 NioServerSocketChannel同NioSocketChannel 致于其它不常用不在研究范围内
NioServerSocketChannel 是给server用的,程序由始至终只有一个NioServerSocketChannel
NioSocketChannel 是给客户端用的,每个连接生成一个NioSocketChannel 对象
NioSocketChannel同NioSocketChannel的继承关系
NioSocketChannel -> AbstractNioByteChannel -> AbstractNioChannel -> AbstractChannel
NioServerSocketChannel -> AbstractNioMessageChannel-> AbstractNioChannel -> AbstractChannel
小提示:如果看文字不够直观可以在eclipse里按快捷键 选择类 ctrl+t

channel有unsafe相应的实现类,反之亦是。其实功能是很简单的,划分太多对象目的是对某部分功能重用,有时也可能因过渡设计造成
对于channel我们主要分析 I/O read/write操作
public class NioServerSocketChannel extends AbstractNioMessageChannel implements io.netty.channel.socket.ServerSocketChannel {
private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER = SelectorProvider.provider();
//构造时就绑定SelectorProvider,然后注册OP_ACCEPT
public NioServerSocketChannel() {
this(newSocket(DEFAULT_SELECTOR_PROVIDER));
}
public NioServerSocketChannel(ServerSocketChannel channel) {
super(null, channel, SelectionKey.OP_ACCEPT);
config = new NioServerSocketChannelConfig(this, javaChannel().socket());
}
/**
server read操作对应的为readMessages
参数是个数组,是C语言书写风格,如果需要返回多种类型数据,那么传个对象进去外部就能获取到
这里比较重要,当有接收到socket时,生成NioSocketChannel对象
读者如果还有印象的话在讲NioEventLoop 有提示netty read 操作是不分 OP_ACCEPT、OP_READ的,可以在这方法打上断点观察
*/
@Override
protected int doReadMessages(List<Object> buf) throws Exception {
SocketChannel ch = javaChannel().accept();
try {
if (ch != null) {
//生成NioSocketChannel
buf.add(new NioSocketChannel(this, ch));
return 1;
}
} catch (Throwable t) {
ch.close();
}
return 0;
}
//server 应该没有write操作才对,因为server是一对多处理,不知道发给那一个clinet
@Override
protected void doWrite(ChannelOutboundBuffer in) throws Exception {}
}
public class NioSocketChannel extends AbstractNioByteChannel implements io.netty.channel.socket.SocketChannel {
public NioSocketChannel(Channel parent, SocketChannel socket) {
super(parent, socket);
config = new NioSocketChannelConfig(this, socket.socket());
}
//////////////////////////////这部分是unsafe底层调用上层的实现//////////////////////////////////////////////
@Override
protected int doReadBytes(ByteBuf byteBuf) throws Exception {
final RecvByteBufAllocator.Handle allocHandle = unsafe().recvBufAllocHandle();
//这里设置byteBuf写入数据坐标
allocHandle.attemptedBytesRead(byteBuf.writableBytes());
return byteBuf.writeBytes(javaChannel(), allocHandle.attemptedBytesRead());
}
@Override
protected int doWriteBytes(ByteBuf buf) throws Exception {
final int expectedWrittenBytes = buf.readableBytes();
return buf.readBytes(javaChannel(), expectedWrittenBytes);
}
@Override
protected void doWrite(ChannelOutboundBuffer in) throws Exception {
for (;;) {
int size = in.size();
//没有数据退出
if (size == 0) {
clearOpWrite();
break;
}
long writtenBytes = 0; //记录写数据size
boolean done = false; //是否完成
boolean setOpWrite = false;
ByteBuffer[] nioBuffers = in.nioBuffers();
int nioBufferCnt = in.nioBufferCount();
long expectedWrittenBytes = in.nioBufferSize();
SocketChannel ch = javaChannel();
//这里有三种分支处理
//如果没有ByteBuffer 有可能只发送几个byte
//1跟default逻辑其实是一样的
switch (nioBufferCnt) {
case 0:
//调用父类 AbstractNioByteChannel doWrite,逻辑基本相同,不同的是AbstractNioByteChannel处理的是byte 实现调用的是 doWriteBytes(ByteBuf buf)方法。。。
super.doWrite(in);
return;
case 1:
//这里只循环16次,可以看出是复制下面代码的哈。。。
ByteBuffer nioBuffer = nioBuffers[0];
for (int i = config().getWriteSpinCount() - 1; i >= 0; i --) {
final int localWrittenBytes = ch.write(nioBuffer);
if (localWrittenBytes == 0) {
setOpWrite = true;
break;
}
expectedWrittenBytes -= localWrittenBytes;
writtenBytes += localWrittenBytes;
if (expectedWrittenBytes == 0) {
done = true;
break;
}
}
break;
default:
//多个ByteBuffer时跟上面逻辑一样
for (int i = config().getWriteSpinCount() - 1; i >= 0; i --) {
final long localWrittenBytes = ch.write(nioBuffers, 0, nioBufferCnt);
if (localWrittenBytes == 0) {
setOpWrite = true;
break;
}
expectedWrittenBytes -= localWrittenBytes;
writtenBytes += localWrittenBytes;
if (expectedWrittenBytes == 0) {
done = true;
break;
}
}
break;
}
// Release the fully written buffers, and update the indexes of the partially written buffer.
in.removeBytes(writtenBytes);
if (!done) {
// Did not write all buffers completely.
incompleteWrite(setOpWrite);
break;
}
}
}
}
public abstract class AbstractChannel extends DefaultAttributeMap implements Channel {
//生成NioSocketChannel时就绑定 unsafe pipeline
protected AbstractChannel(Channel parent) {
this.parent = parent;
id = newId();
unsafe = newUnsafe();
pipeline = newChannelPipeline();
}
}
protected abstract class AbstractUnsafe implements Unsafe {
private void register0(ChannelPromise promise) {
try {
if (!promise.setUncancellable() || !ensureOpen(promise)) {
return;
}
boolean firstRegistration = neverRegistered;
doRegister();
// doRegister 是调用 AbstractNioChannel selectionKey = javaChannel().register(eventLoop().selector, 0, this);
neverRegistered = false;
registered = true;
//这里是添加 Handler 每个Handler会生成一个Context
pipeline.invokeHandlerAddedIfNeeded();
safeSetSuccess(promise);
//通知Handler Registered
pipeline.fireChannelRegistered();
if (isActive()) {
if (firstRegistration) {
//通知Handler Active
pipeline.fireChannelActive();
} else if (config().isAutoRead()) {
beginRead();
}
}
} catch (Throwable t) {
//.......
}
}
}
小结:看似很复杂的Channel实现其实没想象难,大多数读写坐标记录交给ByteBuf处理掉了
1.server每个client连接转换成NioSocketChannel对象
2.构建NioSocketChannel时就已经生成 unsafe、pipeline
[编织消息框架][netty源码分析]8 Channel 实现类NioSocketChannel职责与实现的更多相关文章
- [编织消息框架][netty源码分析]6 ChannelPipeline 实现类DefaultChannelPipeline职责与实现
ChannelPipeline 负责channel数据进出处理,如数据编解码等.采用拦截思想设计,经过A handler处理后接着交给next handler ChannelPipeline 并不是直 ...
- [编织消息框架][netty源码分析]3 EventLoop 实现类SingleThreadEventLoop职责与实现
eventLoop是基于事件系统机制,主要技术由线程池同队列组成,是由生产/消费者模型设计,那么先搞清楚谁是生产者,消费者内容 SingleThreadEventLoop 实现 public abst ...
- [编织消息框架][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源码分析]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源码分析]7 Unsafe 实现类NioSocketChannelUnsafe职责与实现
Unsafe 是channel的内部接口,从书写跟命名上看是不公开给开发者使用的,直到最后实现NioSocketChannelUnsafe也没有公开出去 public interface Channe ...
- [编织消息框架][netty源码分析]13 ByteBuf 实现类CompositeByteBuf职责与实现
public class CompositeByteBuf extends AbstractReferenceCountedByteBuf implements Iterable<ByteBuf ...
随机推荐
- java中的GC(gabage collection)如何工作
1. “引用记数(reference counting)”是一种简单但速度很慢的垃圾回收技术.每个对象都含有一个引用记数器,当有引用连接至对象时,引用计数加1.当引用离开作用域或被置 为null时,引 ...
- JS第二弹:用Jquery组装html标签,输出到页面
用Ajax从服务端获取数据,遍历到表格中(其实将表格替换了),中间发现不能为新增的元素绑定事件,原来是没有将其作为JQ对象
- Python函数之lambda,内置函数,yield生成器等
lambda 1,用于处理简单逻辑 2,自动返回数据(return) 单参数 >>> func2 = lambda a: a+1>>> result = func2 ...
- 项目自动构建工具对比(Maven、Gradle、Ant)
Java世界中主要有三大构建工具:Ant.Maven和Gradle.经过几年的发展,Ant几乎销声匿迹.Maven也日薄西山,而Gradle的发展则如日中天. Maven的主要功能主要分为5点,分别是 ...
- 自己编写jQuery动态引入js文件插件 (jquery.import.dynamic.script)
这个插件主要是结合jquery或者xhr异步请求来使用的,它可以把已经引入过的js文件记录在浏览器内存中,当下次再引入相同的文件就忽略该文件的引入. 此插件不支持浏览器刷新保存数据,那需要利用cook ...
- 数塔,杭电oj-2048
原题地址:http://i.cnblogs.com/EditPosts.aspx?postid=4077291 [Problem Description] 在讲述DP算法的时候,一个经典的例子就是数塔 ...
- 刑天DDOS攻击器下一版本即将使用NTP放大功能
刑天DDOS攻击器下一版本即将使用NTP放大功能 在一次无语实验中无意发现NTP方法后的攻击流量相当可观,Linux实测G口高达30G,也就是说最大可以放大30倍的攻击流量是何等的威武.而 ...
- java虚拟机学习-JVM内存管理:深入Java内存区域与OOM(3)
概述 Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 对于从事C.C++程序开发的开发人员来说,在内存管理领域,他们即是拥有最高权力的皇帝又 ...
- 创建发布自己的npm包
我们基于nodejs平台上面的npm上,可以随意下载很多npm安装包.那我们如何创建自己的npm包呢?很简单,废话少说,开始做~ 开始做之前nodejs默认是要安装的,怎么安装自行百度其他教程. 首先 ...
- 快速找到ARP病毒源
第一招:使用Sniffer抓包 在网络内任意一台主机上运行抓包软件,捕获所有到达本机的数据包.如果发现有某个IP不断发送请求包,那么这台电脑一般就是病毒源.原理:无论何种ARP病毒变种,行为方式有两种 ...