目录
NioSocketChannel的创建
回到上一小节的read()方法
我们首先看readBuf
jdk底层相关的内容
跟到父类构造方法中
我们跟进其构造方法
前文传送门:Netty客户端处理接入事件handle创建

NioSocketChannel的创建
回到上一小节的read()方法
public void read() {
//必须是NioEventLoop方法调用的, 不能通过外部线程调用
assert eventLoop().inEventLoop();
//服务端channel的config
final ChannelConfig config = config();
//服务端channel的pipeline
final ChannelPipeline pipeline = pipeline();
//处理服务端接入的速率
final RecvByteBufAllocator.Handle allocHandle = unsafe().recvBufAllocHandle();
//设置配置
allocHandle.reset(config);
boolean closed = false;
Throwable exception = null;
try {
try {
do {
//创建jdk底层的channel
//readBuf用于临时承载读到链接
int localRead = doReadMessages(readBuf);
if (localRead == 0) {
break;
}
if (localRead < 0) {
closed = true;
break;
}
//分配器将读到的链接进行计数
allocHandle.incMessagesRead(localRead);
//连接数是否超过最大值
} while (allocHandle.continueReading());
} catch (Throwable t) {
exception = t;
}
int size = readBuf.size();
//遍历每一条客户端连接
for (int i = 0; i < size; i ++) {
readPending = false;
//传递事件, 将创建NioSokectChannel进行传递
//最终会调用ServerBootstrap的内部类ServerBootstrapAcceptor的channelRead()方法
pipeline.fireChannelRead(readBuf.get(i));
}
readBuf.clear();
allocHandle.readComplete();
pipeline.fireChannelReadComplete();
//代码省略
} finally {
//代码省略
}
}
我们继续剖析int localRead = doReadMessages(readBuf)这一部分逻辑

我们首先看readBuf
private final List<Object> readBuf = new ArrayList<Object>();
这里只是简单的定义了一个ArrayList, doReadMessages(readBuf)方法就是将读到的链接放在这个list中, 因为这里是NioServerSocketChannel所以这走到了NioServerSocketChannel的doReadMessage()方法

跟到doReadMessage()方法中:
protected int doReadMessages(List<Object> buf) throws Exception {
//根据当前jdk底层的serverSocketChannel拿到jdk底层channel
SocketChannel ch = javaChannel().accept();
try {
if (ch != null) {
//封装成一个NioSokectChannel扔到buf中
buf.add(new NioSocketChannel(this, ch));
return 1;
}
} catch (Throwable t) {
//代码省略
}
return 0;
}
jdk底层相关的内容
首先根据jdk的ServerSocketChannel拿到jdk的Channel, 熟悉Nio的小伙伴应该不会陌生

封装成一个NioSokectChannel扔到Readbuf中

这里的NioSocketChannel是对jdk底层的SocketChannel的包装, 我们看到其构造方法传入两个参数, this代表当前NioServerSocketChannel, ch代表jdk的SocketChannel

我们跟到NioSocketChannel的构造方法中:
public NioSocketChannel(Channel parent, SocketChannel socket) {
super(parent, socket);
config = new NioSocketChannelConfig(this, socket.socket());
}]
这里看到调用了父类构造方法, 传入两个参数, parent代表创建自身channel的, NioServerSocketChannel, socket代表jdk底层的socketChannel

跟到父类构造方法中
protected AbstractNioByteChannel(Channel parent, SelectableChannel ch) {
super(parent, ch, SelectionKey.OP_READ);
}
其中SelectionKey.OP_READ代表其监听事件是读事件

继续跟父类的构造方法:
protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
super(parent);
this.ch = ch;
this.readInterestOp = readInterestOp;
try {
//设置为非阻塞
ch.configureBlocking(false);
} catch (IOException e) {
//代码省略
}
}
这里初始化了自身成员变量ch, 就是jdk底层的SocketChannel, 并初始化了自身的监听事件readInterestOp, 也就是读事件

ch.configureBlocking(false)这一步熟悉nio的小伙伴也不陌生, 就是将jdk的SocketChannel设置为非阻塞

我们继续跟到父类构造方法中
protected AbstractChannel(Channel parent) {
this.parent = parent;
id = newId();
unsafe = newUnsafe();
pipeline = newChannelPipeline();
}
这里初始化parent, 也就是创建自身的NioServerSocketChannel, 并为自身创建了唯一id

初始化unsafe, 我们跟到newUnsafe()方法中

由于此方法是NioEventLoop调用的, 所以会走到其父类AbstractNioByteChannel的newUnsafe()

跟到newUnsafe()中:
protected AbstractNioUnsafe newUnsafe() {
return new NioByteUns
afe();
这里创建了NioByteUnsafe对象, 所以NioSocketChannel对应的unsafe是NioByteUnsafe

继续往下跟, 我们看到其初始化了pipeline, 有关pipline的知识, 我们会在下一章节中讲到

回到NioSocketChannel中的构造方法:
public NioSocketChannel(Channel parent, SocketChannel socket) {
super(parent, socket);
config = new NioSocketChannelConfig(this, socket.socket());
}
同NioServerSocketChannel一样, 这里也初始化了一个Config属性, 传入两个参数, 当前NioSocketChannel自身和jdk的底层SocketChannel的socket对象

我们跟进其构造方法
private NioSocketChannelConfig(NioSocketChannel channel, Socket javaSocket) {
super(channel, javaSocket);
}
同样, 这个类是NioSocketChannel的内部类

继续跟父类构造方法:
public DefaultSocketChannelConfig(SocketChannel channel, Socket javaSocket) {
super(channel);
if (javaSocket == null) {
throw new NullPointerException(“javaSocket”);
}
//保存当前javaSocket
this.javaSocket = javaSocket;
//是否禁止Nagle算法
if (PlatformDependent.canEnableTcpNoDelayByDefault()) {
try {
setTcpNoDelay(true);
} catch (Exception e) {
}
}
这里保存了SocketChannel的socket对象, 并且默认的情况禁止了Nagle算法, 有关Nagle, 感兴趣的同学可以学习下相关知识

继续跟到父类构造方法中:
public DefaultChannelConfig(Channel channel) {
this(channel, new AdaptiveRecvByteBufAllocator());
}
跟到到了我们熟悉的部分了, 也就是说, 无论NioServerSocketChannel和NioSocketChannel, 最后都会初始化DefaultChannelConfig, 并创建可变ByteBuf分配器, 我们之前小节对此做过详细剖析这里不再赘述, 这部分忘记的内容可以阅读之前小节内容进行回顾

这个分配器什么时候真正分配字节缓冲的呢?我们会在之后的章节进行详细剖析
}

更多相关文章

  1. Android(安卓)启动浏览器的方法
  2. Android蓝牙通信代码
  3. 对比onSaveInstanceState和onRestoreInstanceState
  4. 去掉Android(安卓)app上的Title Bar
  5. 详解 Android(安卓)的 Activity 组件
  6. Android使用SQLite数据库的示例
  7. 【知识点】android代码中设置margin
  8. Android(安卓)最新获取手机内置存储大小,SD卡存储空间大小方法
  9. WebKit – WebKit For Android

随机推荐

  1. 02 Android基础理论
  2. Android SDK 1.6下载地址
  3. Android ListView重要美化属性
  4. Android面试系列文章2018之Android部分We
  5. EditText 的一些属性设置
  6. Android中的Handler的机制与用法详解
  7. Android(安卓)Camera数据流分析全程记录(
  8. 《IT蓝豹》吹雪花demo,学习android传感器
  9. android 编程问题集结1
  10. Android 安全加密:消息摘要Message Digest