草庐IT

c++ - 实现通信超时

coder 2024-06-22 原文

我正在实现一个通过 USB 设备与电机 Controller 通信的类。除了指示通过 comm 链接获取的参数是否“新鲜”的方法外,我的一切都正常工作。到目前为止我所拥有的:

class MyCommClass
{
public:
  bool getSpeed( double *speed );

private:
  void rxThread();

  struct MsgBase 
  { /* .. */ };

  struct Msg1 : public MsgBase
  { /* .. */ };

  struct Msg2 : public MsgBase
  { /* .. */ };

  /* .. */

  struct MsgN : public MsgBase
  { /* .. */ };

  Msg1 msg1;
  Msg2 msg2;
  /* .. */
  MsgN msgn;

  std::map< unsigned long id, MsgBase *msg > messages;
};

rxThead() 是一个在单独线程中运行的无限循环,用于检查 USB 设备的可用消息。每条消息都有一个唯一的标识符,rxThread() 使用该标识符将其粘贴到正确的 msgx 对象中。我需要的是当用户调用 getSpeed() 函数时,它需要能够判断当前速度值是“新鲜”还是“陈旧”,即 msgx 包含速度值的对象在指定的超时期限内更新。所以每个消息对象都需要实现自己的超时(因为它们因消息而异)。

所有消息都是由电机 Controller 周期性发送的,但也有一些消息内容一改变就发送(但如果内容不改变也会周期性发送)。这意味着以高于标称速率的速度接收消息是可以的,但它应该在最大超时期限内至少出现一次。

USB 设备提供时间戳和消息,因此我可以访问该信息。时间戳不反射(reflect)当前时间,它是一个 unsigned long 数字,分辨率为微秒,设备会在每次收到消息时更新它。我怀疑设备只是从我调用它的初始化函数时开始从 0 开始递增。我可以想到的几种不同的实现方式是:

  • 每个消息对象都会启动一个线程,该线程会无限期地等待 (WaitForSingleObject) 超时时间。超时后,它检查计数器变量(在等待之前缓存的)是否已递增。如果不是,它会设置一个标志,将消息标记为过时。每次 rxThread() 更新该消息对象时,计数器都会递增。

  • rxThread() 除了填充消息外,还会遍历消息列表并检查每个消息最后更新的时间戳。如果时间戳超过超时,它会将消息标记为过时。此方法在所需处理量方面可能存在问题。在大多数机器上这可能不是问题,但这段代码需要在速度极慢的“工业计算机”上运行。

我非常感谢您对如何实现这一点的想法和建议。除了我提到的两个之外,我对其他想法持开放态度。我使用的是 Visual Studio 2005,跨平台的可移植性并不是一个大问题,因为 USB 设备驱动程序仅适用于 Windows。目前我正在监视大约 8 条消息,但如果该解决方案足够轻巧,我可以添加多条(也许另外 8 条)而不会遇到处理能力限制,那就太好了。

提前致谢, 阿希什。

最佳答案

如果您不需要在消息变得陈旧时“立即”做某事,我认为如果您在每条消息中同时存储计算机时间和设备时间戳,则可以跳过使用计时器:

#include <ctime>
#include <climits>

class TimeStamps {
public:
  std::time_t sys_time() const;   // in seconds
  unsigned long dev_time() const; // in ms
  /* .. */
};

class MyCommClass {
  /* .. */
private:
  struct MsgBase {
    TimeStamps time;
    /* .. */
  };

  TimeStamps most_recent_time;

  bool msg_stale(MsgBase const& msg, unsigned long ms_timeout) const {
    if (most_recent_time.sys_time() - msg.time.sys_time() > ULONG_MAX/1000)
      return true; // device timestamps have wrapped around
    // Note the subtraction may "wrap".
    return most_recent_time.dev_time() - msg.time.dev_time() >= ms_timeout;
  }
  /* .. */
};

当然,如果您愿意,TimeStamps 可以是 MyCommClass 中的另一个嵌套类。

最后,rxThread() 应该在每次收到消息时设置适当消息的 TimeStamps 对象和 most_recent_time 成员。如果在收到任何其他类型的最后一条消息后它变得陈旧,所有这些都不会将消息检测为陈旧,但是您在问题中的第二个可能的解决方案会有同样的问题,所以也许这无关紧要。如果它确实重要,那么如果 msg_stale() 也比较当前时间,这样的事情仍然有效。

关于c++ - 实现通信超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3818280/

有关c++ - 实现通信超时的更多相关文章

  1. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  2. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  3. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  4. ruby - 简单获取法拉第超时 - 2

    有没有办法在这个简单的get方法中添加超时选项?我正在使用法拉第3.3。Faraday.get(url)四处寻找,我只能先发起连接后应用超时选项,然后应用超时选项。或者有什么简单的方法?这就是我现在正在做的:conn=Faraday.newresponse=conn.getdo|req|req.urlurlreq.options.timeout=2#2secondsend 最佳答案 试试这个:conn=Faraday.newdo|conn|conn.options.timeout=20endresponse=conn.get(url

  5. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

  6. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  7. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  8. MIMO-OFDM无线通信技术及MATLAB实现(1)无线信道:传播和衰落 - 2

     MIMO技术的优缺点优点通过下面三个增益来总体概括:阵列增益。阵列增益是指由于接收机通过对接收信号的相干合并而活得的平均SNR的提高。在发射机不知道信道信息的情况下,MIMO系统可以获得的阵列增益与接收天线数成正比复用增益。在采用空间复用方案的MIMO系统中,可以获得复用增益,即信道容量成倍增加。信道容量的增加与min(Nt,Nr)成正比分集增益。在采用空间分集方案的MIMO系统中,可以获得分集增益,即可靠性性能的改善。分集增益用独立衰落支路数来描述,即分集指数。在使用了空时编码的MIMO系统中,由于接收天线或发射天线之间的间距较远,可认为它们各自的大尺度衰落是相互独立的,因此分布式MIMO

  9. 【Java入门】使用Java实现文件夹的遍历 - 2

    遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg

  10. ruby-on-rails - Rails 优雅地处理超时 session ? - 2

    使用rails4,ruby2。我在rails配置中为我的cookiesession设置了30分钟的超时时间。问题是,如果我转到表单,让session超时,然后提交表单,我会收到此ActionController::InvalidAuthenticityToken错误。如何在Rails中优雅地处理这个错误?比如说,重定向到登录屏幕? 最佳答案 在您的ApplicationController:rescue_fromActionController::InvalidAuthenticityTokendoredirect_tosome_p

随机推荐