在使用Netty進行網絡編程的時候,通常需要在網絡連接的不同階段進行相應的操作,比如在連接建立時,客戶端向服務端發起認證,在接收到數據時對數據內容進行解析等等。那么,連接的不同階段在netty中如何表示呢? 這便是本文討論的內容,Netty中ChannelHandller的生命周期。
首先我們先分析小網絡連接的生命周期,連接建立 ---> 數據交互 ---> 連接斷開,在數據交互階段,包括從連接中讀取數據和向連接中寫入數據。知道了連接的生命周期,就可以按圖索驥的在各個階段進行想要的操作。而在Netty中,網絡連接的不同生命周期都可以通過回調的方式來綁定相應的邏輯,這個回調接口就是ChannelHandler
,這里主要我們以ChannelInboundHandler
為例進行分析。在ChannelInboundHandler
中定義了如下和生命周期相關的接口:
- channelRegistered
- channelUnregistered
- channelActive
- channelInactive
- channelRead
- channelReadComplete
加上在父類``中定義的兩個:
- handlerAdded
- handlerRemoved
這些回調接口的調用書序是什么呢?我們通過寫一個LifeCycleHandler
來看下ChannelInboundHandler的生命周期的順序。
public class LifeCycleInBoundHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRegistered(ChannelHandlerContext ctx)
throws Exception {
out.println("channelRegistered: channel注冊到NioEventLoop");
super.channelRegistered(ctx);
}
@Override
public void channelUnregistered(ChannelHandlerContext ctx)
throws Exception {
out.println("channelUnregistered: channel取消和NioEventLoop的綁定");
super.channelUnregistered(ctx);
}
@Override
public void channelActive(ChannelHandlerContext ctx)
throws Exception {
out.println("channelActive: channel准備就緒");
super.channelActive(ctx);
}
@Override
public void channelInactive(ChannelHandlerContext ctx)
throws Exception {
out.println("channelInactive: channel被關閉");
super.channelInactive(ctx);
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg)
throws Exception {
out.println("channelRead: channel中有可讀的數據" );
super.channelRead(ctx, msg);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx)
throws Exception {
out.println("channelReadComplete: channel讀數據完成");
super.channelReadComplete(ctx);
}
@Override
public void handlerAdded(ChannelHandlerContext ctx)
throws Exception {
out.println("handlerAdded: handler被添加到channel的pipeline");
super.handlerAdded(ctx);
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx)
throws Exception {
out.println("handlerRemoved: handler從channel的pipeline中移除");
super.handlerRemoved(ctx);
}
}
啟動服務器和Client,連接成功后,斷開client的連接,Server端輸出結果如下:
handlerAdded: handler被添加到channel的pipeline
channelRegistered: channel注冊到NioEventLoop
channelActive: channel准備就緒
channelRead: channel中有可讀的數據
channelReadComplete: channel讀數據完成
channelReadComplete: channel讀數據完成
channelInactive: channel被關閉
channelUnregistered: channel取消和NioEventLoop的綁定
handlerRemoved: handler從channel的pipeline中移除
從上面結果可以知道,從連接建立到連接斷開,handler的生命周期回調接口調用順序如下:
handlerAdded -> channelRegistered
-> channelActive -> channelRead -> channelReadComplete
-> channelInactive -> channelUnRegistered -> handlerRemoved
下面具體說下每個回調的具體含義:
- handlerAdded: 新建立的連接會按照初始化策略,把handler添加到該channel的pipeline里面,也就是channel.pipeline.addLast(new LifeCycleInBoundHandler)執行完成后的回調;
- channelRegistered: 當該連接分配到具體的worker線程后,該回調會被調用。
- channelActive:channel的准備工作已經完成,所有的pipeline添加完成,並分配到具體的線上上,說明該channel准備就緒,可以使用了。
- channelRead:客戶端向服務端發來數據,每次都會回調此方法,表示有數據可讀;
- channelReadComplete:服務端每次讀完一次完整的數據之后,回調該方法,表示數據讀取完畢;
- channelInactive:當連接斷開時,該回調會被調用,說明這時候底層的TCP連接已經被斷開了。
- channelUnREgistered: 對應channelRegistered,當連接關閉后,釋放綁定的workder線程;
- handlerRemoved: 對應handlerAdded,將handler從該channel的pipeline移除后的回調方法。
