Netty:实现同步发送并接收消息的一种方式

16 篇文章 0 订阅
3 篇文章 0 订阅

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属性。


  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值