国产精品chinese,色综合天天综合精品网国产在线,成午夜免费视频在线观看,清纯女学生被强行糟蹋小说

    <td id="ojr13"><tr id="ojr13"><label id="ojr13"></label></tr></td>
        • <source id="ojr13"></source>
            <td id="ojr13"><ins id="ojr13"><label id="ojr13"></label></ins></td>

            Article / 文章中心

            netty自帶http2的編碼解碼器framecodec

            發(fā)布時(shí)間:2021-11-25 點(diǎn)擊數(shù):641

            簡(jiǎn)介

            netty為我們提供了很多http2的封裝,讓我們可以輕松的搭建出一個(gè)支持http2的服務(wù)器。其中唯一需要我們自定義的就是http2 handler。

            在之前的文章中,我們介紹了自定義http2handler繼承自Http2ConnectionHandler并且實(shí)現(xiàn)Http2FrameListener。這種實(shí)現(xiàn)方式是netty目前比較推薦的實(shí)現(xiàn)方式,今天給大家介紹的一種實(shí)現(xiàn)方式是netty中準(zhǔn)備替換繼承Http2ConnectionHandler的實(shí)現(xiàn)方式,但是這種實(shí)現(xiàn)方式并不成熟,還在不斷的完善中。

            今天給大家介紹一下這種實(shí)現(xiàn)方式。

            Http2FrameCodec

            這種實(shí)現(xiàn)方式的核心類是Http2FrameCodec。事實(shí)上Http2FrameCodec也是繼承自Http2ConnectionHandler。

            它的主要作用是將HTTP/2中的frames和Http2Frame對(duì)象進(jìn)行映射。Http2Frame是netty中對(duì)應(yīng)所有http2 frame的封裝,這樣就可以在后續(xù)的handler中專注于處理Http2Frame對(duì)象即可,從而擺脫了http2協(xié)議的各種細(xì)節(jié),可以減少使用者的工作量。

            對(duì)于每個(gè)進(jìn)入的HTTP/2 frame,Http2FrameCodec都會(huì)創(chuàng)建一個(gè)Http2Frame對(duì)象,并且將其傳遞給channelRead方法,用于對(duì)該對(duì)象進(jìn)行處理。

            通過(guò)調(diào)用write方法,可以對(duì)outbound的 Http2Frame 轉(zhuǎn)換成為http2 frame的格式。

            Http2Frame、Http2FrameStream和Http2StreamFrame

            netty中有三個(gè)非常類似的類,他們是Http2Frame、Http2FrameStream和Http2StreamFrame。

            我們知道netty中一個(gè)tcp連接可以建立多個(gè)stream,Http2FrameStream就是和stream對(duì)應(yīng)的類,這個(gè)類中包含了stream的id和stream當(dāng)前的狀態(tài)。

            一個(gè)stream中又包含了多個(gè)消息,每個(gè)消息都是由多個(gè)frame組成的,所以Http2Frame是和這些frame對(duì)應(yīng)的netty類。

            Http2StreamFrame本身也是一個(gè)frame,事實(shí)上它繼承自Http2Frame。

            為什么會(huì)有這個(gè)類呢?因?yàn)閷?duì)應(yīng)frame本身來(lái)說(shuō),一般情況下它是和一個(gè)特定的stream相關(guān)聯(lián)的,Http2StreamFrame表示這種關(guān)聯(lián)關(guān)系,可以通過(guò)它的set stream方法來(lái)指定其關(guān)聯(lián)的stream。如果想要該frame應(yīng)用到整個(gè)連接而不是特定的某個(gè)stream,如果是關(guān)聯(lián)到整個(gè)連接,那么stream()方法的返回就是null。

            Http2FrameCodec的構(gòu)造

            雖然Http2FrameCodec有構(gòu)造函數(shù),但是netty推薦使用Http2FrameCodecBuilder來(lái)構(gòu)造它:

            Http2FrameCodecBuilder.forServer().build();

            可以看到Http2FrameCodecBuilder有一個(gè)forServer還有一個(gè)forClient方法。他們一個(gè)是使用在服務(wù)器端,一個(gè)是使用在客戶端。

            主要是通過(guò)里面的server屬性來(lái)進(jìn)行區(qū)分。

            Stream的生命周期

            frame codec將會(huì)向有效的stream發(fā)送和寫(xiě)入frames。之前講過(guò)了 Http2StreamFrame 是和一個(gè)Http2FrameStream對(duì)象相關(guān)聯(lián)的。

            對(duì)于一個(gè)有效的stream來(lái)說(shuō),如果任意一方發(fā)送一個(gè)RST_STREAM frame,那么該stream就會(huì)被關(guān)閉。

            或者發(fā)送方或者接收方任意一方發(fā)送的frame中帶有END_STREAM標(biāo)記,該stream也會(huì)被關(guān)閉。

            流控制

            Http2FrameCodec提供了對(duì)流的自動(dòng)控制,但是我們?nèi)匀恍枰鲆恍┎僮鳎瑏?lái)對(duì)window進(jìn)行更新。

            具體而言,當(dāng)我們?cè)诮邮盏紿ttp2DataFrame消息的時(shí)候,對(duì)消息進(jìn)行處理之后,需要增大window的大小,表示該data已經(jīng)被處理了,可以有更多的空間去容納新的數(shù)據(jù)。

            也就是說(shuō)需要向ctx中寫(xiě)入一個(gè)Http2WindowUpdateFrame,在這個(gè)Http2WindowUpdateFrame中需要傳入處理的data的大小和對(duì)應(yīng)stream的id,下面是一個(gè)處理data frame的例子:

            /**  * 處理data frame消息  */  private static void onDataRead(ChannelHandlerContext ctx, Http2DataFrame data){  Http2FrameStream stream = data.stream();  if (data.isEndStream()) {  sendResponse(ctx, stream, data.content());  } else {  // 不是end stream不發(fā)送,但是需要釋放引用  data.release();  }  // 處理完data,需要更新window frame,增加處理過(guò)的Data大小  ctx.write(new DefaultHttp2WindowUpdateFrame(data.initialFlowControlledBytes()).stream(stream));  }

            上的例子中,我們向DefaultHttp2WindowUpdateFrame傳入了對(duì)應(yīng)的stream id,如果stream id為0,則表示處理的是整個(gè)connection,而不是單獨(dú)的某個(gè)stream。

            除了window update frame之外,對(duì)于某個(gè)特定stream的初始window還可以發(fā)送一個(gè) Http2SettingsFrame,通過(guò)設(shè)置Http2Settings.initialWindowSize() 達(dá)到初始化的目的。

            接收消息

            對(duì)于每個(gè)HTTP/2 stream來(lái)說(shuō),其中包含的frame可以分為 Http2HeadersFrame和Http2DataFrame,而Http2HeadersFrame必定是第一個(gè)接收到的frame,并且這個(gè)headerFrame還關(guān)聯(lián)了對(duì)應(yīng)的stream對(duì)象:Http2FrameStream。

            所以我們?cè)谔幚淼臅r(shí)候可以針對(duì)這兩種不同的frame分別進(jìn)行處理:

            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {  if (msg instanceof Http2HeadersFrame) {  onHeadersRead(ctx, (Http2HeadersFrame) msg);  } else if (msg instanceof Http2DataFrame) {  onDataRead(ctx, (Http2DataFrame) msg);  } else {  super.channelRead(ctx, msg);  }  }

            自定義handler

            如果使用Http2FrameCodec,我們只需要在pipline中添加Http2FrameCodec之后,再添加自定義的handler即可:

            ctx.pipeline().addLast(Http2FrameCodecBuilder.forServer().build(), new CustHttp2Handler());

            因?yàn)镠ttp2FrameCodec已經(jīng)對(duì)http2中的frame進(jìn)行了轉(zhuǎn)換,所以我們?cè)贑ustHttp2Handler中只需要處理自定義邏輯即可。

            netty推薦自定義的handler繼承自Http2ChannelDuplexHandler,因?yàn)樗绕胀ǖ腃hannelDuplexHandler多了一個(gè)創(chuàng)建newStream()和遍歷所有有效stream的 forEachActiveStream(Http2FrameStreamVisitor)方法。