ChannelHandler有兩個子類ChannelInboundHandler和ChannelOutboundHandler宽气,這兩個類對應(yīng)了兩個數(shù)據(jù)流向,如果數(shù)據(jù)是從外部流入我們的應(yīng)用程序,我們就看做是inbound气嫁,相反便是outbound巨坊。一個ChannelHandler處理完接收到的數(shù)據(jù)會傳給下一個Handler灾票,或者什么不處理,直接傳遞給下一個汞窗。
一個ChannelPipeline可以把兩種Handler(ChannelInboundHandler和ChannelOutboundHandler)混合在一起姓赤,當一個數(shù)據(jù)流進入ChannelPipeline時,它會從ChannelPipeline頭部開始傳給第一個ChannelInboundHandler仲吏,當?shù)谝粋€處理完后再傳給下一個不铆,一直傳遞到管道的尾部。與之相對應(yīng)的是裹唆,當數(shù)據(jù)被寫出時誓斥,它會從管道的尾部開始,先經(jīng)過管道尾部的“最后”一個ChannelOutboundHandler许帐,當它處理完成后會傳遞給前一個ChannelOutboundHandler劳坑。
request------->ChannelInboundHandler1------>ChannelInboundHandler2------>ChannelInboundHandler3------>ChannelOutboundHandler3------>ChannelOutboundHandler2------>ChannelOutboundHandler1---------------->response
數(shù)據(jù)在各個Handler之間傳遞,這需要調(diào)用方法中傳遞的ChanneHandlerContext來操作成畦, 在netty的API中提供了兩個基類分ChannelOutboundHandlerAdapter和ChannelOutboundHandlerAdapter距芬,他們僅僅實現(xiàn)了調(diào)用ChanneHandlerContext來把消息傳遞給下一個Handler,因為我們只關(guān)心處理數(shù)據(jù)循帐,因此我們的程序中可以繼承這兩個基類來幫助我們做這些框仔,而我們僅需實現(xiàn)處理數(shù)據(jù)的部分即可。
我們知道InboundHandler和OutboundHandler在ChannelPipeline中是混合在一起的拄养,那么它們?nèi)绾螀^(qū)分彼此呢离斩?其實很容易,因為它們各自實現(xiàn)的是不同的接口,對于inbound event捐腿,Netty會自動跳過OutboundHandler,相反若是outbound event纵朋,ChannelInboundHandler會被忽略掉。
當一個ChannelHandler被加入到ChannelPipeline中時茄袖,它便會獲得一個ChannelHandlerContext的引用操软,而ChannelHandlerContext可以用來讀寫Netty中的數(shù)據(jù)流。因此宪祥,現(xiàn)在可以有兩種方式來發(fā)送數(shù)據(jù)聂薪,一種是把數(shù)據(jù)直接寫入Channel,一種是把數(shù)據(jù)寫入ChannelHandlerContext蝗羊,它們的區(qū)別是寫入Channel的話藏澳,數(shù)據(jù)流會從Channel的頭開始傳遞,而如果寫入ChannelHandlerContext的話耀找,數(shù)據(jù)流會流入管道中的下一個Handler翔悠。
總結(jié):
在使用Handler的過程中,需要注意:
1野芒、ChannelInboundHandler之間的傳遞蓄愁,通過調(diào)用 ctx.fireChannelRead(msg) 實現(xiàn);調(diào)用ctx.write(msg) 將傳遞到ChannelOutboundHandler狞悲。
2撮抓、ctx.write()方法執(zhí)行后,需要調(diào)用flush()方法才能令它立即執(zhí)行摇锋。
3丹拯、Handler的消費處理放在最后一個處理。
我的Github項目荸恕,歡迎大家指導乖酬!Watch!Star戚炫!Fork! Thanks剑刑!
GitHub-Netty-demo-server
GitHub-Netty-demo-client