開發中希望基於netty開發的客戶端可以既能在啟動時與服務器通訊,又能在指定時間點或事件與服務器通訊,比如主動發送注銷信息。
1. 在啟動時與服務器通訊可以在ChannelHandler的channleActive方法中實現。當客戶端與服務端TCP鏈路建立成功時,Netty的NIO線程會調用channleActive方法,其中可以通過入參ChannelHandlerContext 的writeAndFlush方法發送指令給服務器。這一步是ChannelHandler 添加到ChannelPipeline 之后自動觸發並接入ChannelHandlerContext參數的。
2. 在指定時間點或事件與服務器通訊時,在函數里依然需要ChannelHandlerContext來發送指令,雖然沒有程序可以傳入該參數,但我們實際可以緩存ChannelHandlerContext,並直接使用。
ChannelHandlerContext是在ChannelHandler 添加到 ChannelPipeline 時創建的一個實例,它代表了 ChannelHandler 和ChannelPipeline 之間的關聯。接口ChannelHandlerContext 主要是對通過同一個 ChannelPipeline 關聯的 ChannelHandler 之間的交互進行管理。ChannelHandlerContext 與 ChannelHandler 的關聯從不改變,所以緩存它的引用是安全的。
可以通過重寫handlerAdded函數,緩存ChannelHandlerContext的引用。該函數在ChannelHandler 添加到 ChannelPipeline 時觸發。
代碼如下
public class ClientHandlerDemo extends ChannelDuplexHandler { /**緩存ChannelHandlerContext*/ private ChannelHandlerContext ctx; @Override /*添加到pipeline時自動觸發*/ public void handlerAdded(ChannelHandlerContext ctx) { this.ctx = ctx; } /** * 建立連接時 */ @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { logger.info("嘗試建立連接時間:" + new Date()); ctx.writeAndFlush(buildLogonMessage()); } /** * 關閉連接時 */ @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { logger.info("Handler關閉連接。"); super.channelInactive(ctx); } @Override public void close(ChannelHandlerContext ctx, ChannelPromise future) throws Exception { logger.info("Handler關閉連接處理,時間:" + new Date()); super.close(ctx, future); } /**主動關閉連接*/ public void toClose() { if(ctx == null ) { logger.info("未建立連接。"); return; } logger.info("發送注銷消息,主動關閉連接。"); ctx.channel().writeAndFlush(buildLogoutMessage()).addListener(ChannelFutureListener.CLOSE); } }
參考
https://www.w3cschool.cn/essential_netty_in_action/essential_netty_in_action-bj5a28bq.html
