Netty原始碼分析:1.3初始化NioServerSocketChannel
阿新 • • 發佈:2018-11-21
第一章節是主要是伺服器啟動的程式碼分析。章節目錄有:
|———1.1初始化NioEventLoopGroup
|———1.2初始化NioEventLoop
|———1.3初始化NioServerSocketChannel
|———1.4伺服器啟動流程
為什麼先從初始化開始瞭解伺服器啟動?
因為在我看伺服器啟動的相關原始碼的時候,有很多地方都是初始化的時候已經建立好的。所以我就從初始化的原始碼開始看起。這是我第一次看原始碼的筆記,仍有很多理解錯誤的地方和不解的地方。歡迎討論。
本篇目錄:
- 類的繼承關係圖
- 時序圖
- 程式碼分析
- 疑問
類的繼承關係圖
時序圖
NioServerSocketChannel的構造器
super(null, channel, SelectionKey.OP_ACCEPT);
第一個引數是Channel類
第二個引數是SelectableChannel
第三個引數是int:SelectionKey.OP_ACCEPT
讓我想起了NIO中給一個channel繫結一個selector管理器。
public NioServerSocketChannel(ServerSocketChannel channel) {
super(null, channel, SelectionKey.OP_ACCEPT);
config = new NioServerSocketChannelConfig(this, javaChannel().socket());
}
初始化開始
1. DefaultAttributeMap
首先是從DefaultAttributeMap
開始初始化
該類實現了AttributeMap介面,主要是更加降低損耗。
2. AbstractChannel
- parent 屬性為null: 從
NioServerSocketChannel
的構造器可以知道第一個引數Channel 是null。 - unsafe:新建一個NioMessageUnsafe
- pipeline:新建一個Pipeline。也就是說一個channel一個Pipeline.
netty對底層socket的操作都是通過unsafe來做的。unsafe主要由兩種不同的實現NioMessageUnsafe和NioByteUnsafe.NioMessageUnsafe是服務端的。
protected AbstractChannel(Channel parent) {
this.parent = parent;
id = newId();
unsafe = newUnsafe();
pipeline = newChannelPipeline();
}
3. AbstractNioChannel
- 1 初始化AbstractChannel
- 2 ch的型別是SelectableChannel。就是相當於儲存該selector管理器
- 3 儲存Int ,也就是初始化
SelectionKey.OP_ACCEPT
感興趣事件。 - 4 設定非阻塞模式。相當於nio裡設定channel非阻塞。
protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
super(parent); //1
this.ch = ch; //2
this.readInterestOp = readInterestOp; //3
try {
ch.configureBlocking(false); //4
} catch (IOException e) {
try {
ch.close();
} catch (IOException e2) {
}
}
}
4. AbstractNioMessageChannel
protected AbstractNioMessageChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
super(parent, ch, readInterestOp);
}
5. NioServerSocketChannel
- 1 對Channel進行配置。與
ChannelOption
類類似。
public NioServerSocketChannel(ServerSocketChannel channel) {
super(null, channel, SelectionKey.OP_ACCEPT);
config = new NioServerSocketChannelConfig(this, javaChannel().socket()); //1
}
這樣一個NioServerSocketChannel的物件就已經建立完成了。
總結
整個NioServerSocketChannel的初始化,我覺得就是建立一個channel物件,在該物件裡面附帶一些屬性,這些屬性有:
- unsafe:NioMessageUnsafe
- pipeline管道。
- SelectableChannel並將該Channel設定為非阻塞
- 附帶一個感興趣事件:OP_ACCEPT
- 設定預設的Channel配置。
疑問
unsafe 是什麼?
nterface Unsafe {
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();
}
可以看出,這些方法都是java底層的Socket的操作。
所以回到底層操作,都是需要用到這些方法。
pipeline 的初始化到底做了什麼?
public DefaultChannelPipeline(AbstractChannel channel) {
if (channel == null) {
throw new NullPointerException("channel");
}
this.channel = channel;
tail = new TailContext(this);
head = new HeadContext(this);
head.next = tail;
tail.prev = head;
}
- 首先是Pipeline與channel繫結在一次。也就是Pipeline裡有和channel的引數,用來儲存該例項。
head
和tail
是雙向連結串列的頭和尾。因為Pipeline是一個雙向連結串列。此時頭和尾都是指向自己。