小白帶你認識netty(二)之netty服務端啓動(上)

上一章 中的標準netty啓動代碼中,ServerBootstrap究竟是如何啓動的呢?這一章咱們來瞅下。java

server.group(bossGroup, workGroup);
			server.channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG, 100);
			server.childHandler(new DealNettyServerInitializer());
			

			ChannelFuture future = server.bind(7878).sync();

啓動代碼無非這麼幾行,我一行一行的瞅。服務器

server.group(bossGroup, workGroup);socket

還記得上一章定義的兩個NioEventLoopGroup不?bossGroup和workGroup。這裏的ServerBootstrap的group方法就是將workGroup直接賦值給了該對象的childGroup。而bossGroup傳到了其父類AbstractBootstrap中,進行保存。oop

看到這,咱們知道了兩個類的關係:ServerBootstrap是AbstractBootstrap的子類。this

server.channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG, 100);spa

會將NioServerSocketChannel的class對象做爲參數構建ReflectiveChannelFactory對象。這是什麼對象呢?進去看一下:.net

哦,原來是一個經過反射構建對象的工廠類。回到上一步,netty會把ReflectiveChannelFactory對象做爲參數調用channelFactory()方法。進入這個方法看一下:3d

原來只是保存ReflectiveChannelFactory對象。注意,channel方法是屬於AbstractBootstrap對象的,所以,ReflectiveChannelFactory對象是保存在AbstractBootstrap對象中的。rest

一樣,option方法也是AbstractBootstrap對象的,options會保存該option對象,那這麼說,options應該是一個集合了,netty

果真是一個map集合。

server.childHandler(new DealNettyServerInitializer());

childHandler是屬於ServerBootstrap類的,因此將DealNettyServerInitializer對象賦值給了ServerBootstrap的childHandler成員變量。

至此,只是保存變量,沒有使用。看下server.bind(7878)方法,此方法就是服務器啓動的真正入口。

很簡單,繼續跟進,

調用doBind方法,繼續跟進:

這麼多代碼,主要是initAndRegister方法,所以跟進去。

下面正式進入啓動流程,啓動流程大致分爲4步:

一、建立服務端channel:NioServerSocketChannel

二、初始化服務端Channel:NioServerSocketChannel

三、註冊Selector:將Channel註冊到Selector上

四、端口的綁定:服務端端口的監聽。

下面,一步一步的分析:

一、建立服務端channel:NioServerSocketChannel

忘了說了,這個bind方法是調用的AbstractBootstrap的方法哦,所以這個channelFactory就是channel()方法的參數ReflectiveChannelFactory,下圖爲證:

還記的ReflectiveChannelFactory的newChannel方法嗎?

很明顯,就是經過反射構建NioServerSocketChannel。由於咱們傳入的是NioServerSocketChannel的Class對象。

NioServerSocketChannel對象是生成了,咱們一塊兒看一下這個NioServerSocketChannel的構造方法吧。

這個newSocket是作了什麼?

哦,原來是調用jdk的代碼,生成Nio的ServerSocketChannel呀。繼續查看:

跟進this:

記住,這裏的第三個參數是accept事件,,後續咱們還會提到。跟進父類的構造方法:

咱們能夠看到,NioServerSocketChannel的父類是AbstractNioMessageChannel。而後這個構造方法只是繼續調用父類的構造方法。

咱們又知道了,AbstractNioMessageChannel的父類是AbstractNioChannel。而且剛纔說注意的accept事件,賦值給了AbstractNioChannel的成員變量readInterestOp,後續還會遇到。

注意這個方法,ch是什麼?就是傳進來的jdk原生的ServerSocketChannel,一次該方法明顯是將此通道將被置於非阻塞模式。

繼續跟進父類的構造方法:

咱們又知道了AbstractNioChannel的父類是AbstractChannel。而且,在該構造方法中,實例化了id,unsafe和pipeline。

明顯此處的NioMessageUnsafe的父類是AbstracNioUnsafe。

到這裏,一系列的父類構造方法的調用結束了。咱們先總結下他們之間的關係。

NioServerSocketChannel的父類是AbstractNioMessageChannel;AbstractNioMessageChannel的父類是AbstractNioChannel;AbstractNioChannel的父類是AbstractChannel;還有一個額外的關係

NioMessageUnsafe的父類是AbstractNioUnsafe。

即:

NioServerSocketChannel -> AbstractNioMessageChannel -> AbstractNioChannel -> AbstractChannel;

NioMessageUnsafe -> AbstractNioUnsafe

爲啥非要強調這種繼承關係?由於後續的調用很複雜,若是不記住他們的關係,很容易分不清楚變量是從何 而來的。。

好了,我再回到開始的NioServerSocketChannel的構造方法上:

看過了super一系列的調用,咱們瞅下下面的代碼。先看下javaChannel()幹了什麼?

調用了父類的javaChannel方法。NioServerSocketChannel的父類是AbstractNioMessageChannel,所以看AbstractMessageNioChannel類的javaChannel方法,咱們發現AbstractMessageNioChannel類中並無javaChannel方法,所以應該調用的是AbstractNioMessageChannel的父類AbstractNioChannel的javaChannel,咱們看一下:

這個ch,不就是以前傳入的jdk原聲的ServerSocketChannel對象麼。。。圖下證:

所以javaChannel方法,獲取的是原生的ServerSocketChannel對象。點個贊,這個方法的名字真是見名知意呀。那javaChannel().socket()咱們就很容易知道了,就是打開一個socket鏈接。並將該鏈接封裝到NioServerSocketChannelConfig對象中保存在NioServerSocketChannel的config成員變量上。至此,建立服務端channel:NioServerSocketChannel完成。

 

二、初始化服務端Channel:NioServerSocketChannel

回到initAndRegister方法,看完了NioServerSocketChannel的實例化,咱們看下緊接着的代碼init():

進入init方法:

哎呦,這個又一坨代碼。。。。不要緊,不少代碼都很簡單:

上面代碼很簡單,就是setChannelOptions和setChannelAttrs。

同理,setChildOptions和setChildAttrs。

首先聲明下,initChannel方法不是當即被調用的哦,後面會講到什麼時候被調用。總之會被調用,但不是這裏。

p是啥,,這個p就是NioServerSocketChannel裏成員變量,準確的說是父類父類父類的成員變量,即AbstractChannel的成員變量。下圖證:

那個initChannel的方法裏的pipeline變量也是p。那pipeline是啥呢?之後會講的,這裏只要知道它是一個雙向鏈表結構就能夠了。

所以這段的意思是將handler對象放入到pipeline中。

看到這裏,一下懵了,NioServerSocketChannel裏面啥時候實例化的EventLoop對象呀?說明下,此刻尚未實例化,由於沒有調用該方法,因此暫時不會又null異常。

這段的邏輯就是向pipeline中添加鏈接器ServerBootstrapAcceptor。

好了,今天先到這,下面兩步代碼太深,明天再繼續吧。最後,必定要記住繼承的關係。

相關文章
相關標籤/搜索