Netty:實現同步發送並接收消息的一種方式

Netty創建通信服務時使用Nio異步通信, 配置代碼(bootstrap.channel(NioSocketChannel.class);),要怎樣實現這樣一個同步發送消息並接收消息功能,雖然這樣做覺得很沒必要。


public class ChannelUtil {
	
	public static Object writeMsgSync(Object msg, Channel channel, AttributeKey<Object> attrKey, int timeout) throws Exception{
		if(channel.isActive()){
			synchronized(channel){
				Attribute<Object> attr = channel.attr(attrKey);
				synchronized(attr){
					attr.set(msg);
					System.out.println("發消息:"+msg);
					channel.writeAndFlush(msg);
					attr.wait(timeout * 1000);
					Object ret = attr.get();
					System.out.println("收消息:"+ret);
					attr.set(null);
					if(ret == msg){
						return null;
					}
					return ret;
				}
			}
		}
		return null;
	}
}

下面的方法需要加入到收消息的Handler(如SimpleChannelInboundHandler)中


@Override
	public void onRead(ChannelHandlerContext ctx, CmdMsg msg) throws Exception {
		System.out.println("收到消息:"+msg);
		Channel channel = ctx.channel();
		Attribute<Object> attr = channel.attr(ClientGlobal.CHANNEL_SYNC_KEY);
		synchronized(attr){
			Object lastMsg = attr.get();
			if (lastMsg != null && lastMsg instanceof CmdMsg) {
				CmdMsg lastCmdMsg = (CmdMsg) lastMsg;
				if (msg.getCmdCode() == lastCmdMsg.getCmdCode()) {
					// 當前消息就是正在等待返回的響應消息,同步消息
					attr.set(msg);
					attr.notify();
					System.out.println("此消息是同步響應消息:" + msg);
					return;
				}
				else{
					if(msg.getCmdCode() == CmdConst.CMD_RET){
						RetMsg retMsg = (RetMsg)PackUtil.unpackCmdMsg(msg, RetMsg.class);
						if(retMsg.getOpCode() == lastCmdMsg.getCmdCode()){
							attr.set(msg);
							attr.notify();
							System.out.println("此消息是同步響應消息:" + msg);
							return;
						}
					}

				}
			}
		}
		System.out.println("消息加入到隊列中:"+msg);
		MsgTask msgTask = new MsgTask();
		msgTask.setCtx(ctx);
		msgTask.setMsg(msg);
		BaseProcessor<?> processor = msgModule.getMsgProcessor(msg.getCmdCode());
		if(processor == null){
			//沒有註冊對應的消息加工器
			System.out.println("沒有註冊對應的消息加工器:msg code is "+msg.getCmdCode());
			return;
		}
		msgTask.setProcessor(processor);
		msgGueueMgr.pushMsgTask(msgTask);
	}

實現原理:通過Channel和Channel中的Attribute,利用wait、Notify,實現線程間通信

1: 發送消息時,將channel中的屬性設值,然後提交到Netty內部消息隊列,等待一個超時時間,如果這段時間內,有人將其喚醒,則取出channel的屬性值,這個就是返回的消息;

2:接收消息時,判斷channel中的屬性是否有設值,若有,判斷當前消息是否是此屬性中消息的響應消息,若是,則喚醒channel屬性。


發佈了35 篇原創文章 · 獲贊 15 · 訪問量 19萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章