欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 美食 > Netty向设备发送消息并等待设备响应

Netty向设备发送消息并等待设备响应

2024/10/25 8:20:34 来源:https://blog.csdn.net/StruggleRookie/article/details/139552413  浏览:    关键词:Netty向设备发送消息并等待设备响应

在使用netty开发和硬件对接时,经常会遇到服务端给硬件设备发送命令后需要等待设备反馈响应命令后执行逻辑。

一、定义同步等待

/*** @author: 晨光* @description: 同步等待* @Version 1.0*/
public class SyncPromise {// 用于接收结果private BaseMessageInfoVo messageResponse;//CountDownLatch可以看作是一个计数器,当计数器的值减到0时,所有等待的线程将被释放并继续执行。private final CountDownLatch countDownLatch = new CountDownLatch(1);// 用于判断是否超时private boolean isTimeout = false;/*** 同步等待返回结果* timeout 超时时间    unit 时间单位*/public BaseMessageInfoVo get(long timeout, TimeUnit unit) throws InterruptedException {// 等待阻塞,超时时间内countDownLatch减到0,将提前唤醒,以此作为是否超时判断// 如果在指定时间内计数器仍未归零,则返回false,否则返回true。boolean earlyWakeUp = countDownLatch.await(timeout, unit);if(earlyWakeUp) {// 超时时间内countDownLatch减到0,提前唤醒,说明已有结果return messageResponse;} else {// 超时时间内countDownLatch没有减到0,自动唤醒,说明超时时间内没有等到结果isTimeout = true;return null;}}// 计数器清零,唤醒public void wake() {countDownLatch.countDown();}public BaseMessageInfoVo getMessageResponse() {return messageResponse;}public void setMessageResponse(BaseMessageInfoVo messageResponse) {this.messageResponse = messageResponse;}public boolean isTimeout() {return isTimeout;}
}

2、定义工具类发送同步消息

/*** @author: 晨光* @description: 定义工具类* @Version 1.0*/
public class SyncUtil {private final static Map<String, SyncPromise> syncPromiseMap =  new ConcurrentHashMap<>();//key 唯一主键类,方便在处理逻辑中找到唤醒public static BaseMessageInfoVo send(String key,Channel channel,BaseMessageInfoVo messageRequest, long timeout, TimeUnit unit) throws Exception{if(channel == null) {throw new NullPointerException("channel");}if(messageRequest == null) {throw new NullPointerException("rpcRequest");}if(timeout <= 0) {throw new IllegalArgumentException("timeout must greater than 0");}// 创造一个容器,用于存放当前线程与rpcClient中的线程交互SyncPromise syncPromise = new SyncPromise();syncPromiseMap.put(key, syncPromise);// 发送消息,此处如果发送玩消息并且在get之前返回了结果,下一行的get将不会进入阻塞,也可以顺利拿到结果channel.writeAndFlush(messageRequest);// 等待获取结果BaseMessageInfoVo messageResponse = syncPromise.get(timeout, unit);if(messageResponse == null) {if(syncPromise.isTimeout()) {throw new TimeoutException("等待响应结果超时");} else{throw new Exception("其他异常");}}// 移除容器syncPromiseMap.remove(header+ ChannelMap.getEquipCode(channel));return messageResponse;}public static Map<String, SyncPromise> getSyncPromiseMap(){return syncPromiseMap;}
}

通过上面的类即可同步向设备发送命令。

3、在设备返回命令的逻辑中对应唤醒处理逻辑

/*** 连接管理 handler*/
@Slf4j
@Service
@ChannelHandler.Sharable
public class SyncRequestHandler extends SimpleChannelInboundHandler<BaseMessageInfoVo> { //ChannelInboundHandlerAdapter@Overrideprotected void channelRead0(ChannelHandlerContext ctx, BaseMessageInfoVo resp) throws Exception {//查询相应key对应的是否有返回,如果有返回就唤醒,直接返回响应数据SyncPromise syncPromise = SyncUtil.getSyncPromiseMap().get(resp.getHeader()+ChannelMap.getEquipCode(ctx.channel()));if(syncPromise != null){//在获取对象不为null时执行唤醒操作,否则直接丢弃syncPromise.setMessageResponse(resp);syncPromise.wake();}}
}

4、具体的调用发送命令处理逻辑

BaseMessageInfoVo responseInfo = SyncUtil.send(MessageConstant.UPGRADE_PREIX, channel, baseMessageInfoVo, 5, TimeUnit.SECONDS);
System.out.println(JSONObject.toJSONString(responseInfo));//根据具体逻辑进行判断
return ApiResult.success(responseInfo.getHeader()+responseInfo.getData(),"发送成功");

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com