【问题标题】:C++ Cross Platform Timeout readsC++ 跨平台超时读取
【发布时间】:2013-11-06 06:59:40
【问题描述】:

我正在为在AI competition 中竞争的机器人实现测试服务器,机器人通过标准输入/输出与服务器通信。机器人轮到他们的时间只有这么长。在之前的 AI 竞赛中,我在 Java 中编写了服务器,并通过使用 BlockingQueue 和线程对进程流进行阻塞读/写来处理。

本次比赛希望使用 C++。我找到了Boost.Process 和 Boost.Asio,但据我所知,Asio 库没有办法超时等待读取多长时间。它的设计是围绕使用回调函数来告诉您读取何时完成。而我想阻止但最大超时。我可以使用特定于平台的 API(如 select)来执行此操作,但要寻找更多的跨平台解决方案。有什么建议吗?

编辑:为了澄清我想要一个类 BotConnection 来处理与具有两种方法的机器人进程进行通信,例如:string readLine(long timeoutInMilliseconds) 和 void writeLine(string line, long timeoutInMilliseconds)。所以调用代码的编写就像使用阻塞调用一样,但可以超时(抛出异常或更改上面的方法签名,因此如果操作完成或超时,则返回成功标志)

【问题讨论】:

  • 我的另一个想法是在 Boost.Process 的输入/输出流周围使用 C++11 线程,就像在 java 解决方案中一样。
  • ‘select‘ 和 ‘poll’ 提供带有可选超时的 io 等待
  • 哪些平台?如果都是 unix,select 可能是最便携的。如果你需要混合窗户,我不确定。
  • 主要是我想支持的 windows 和 linux 平台。 IIRC 窗口选择仅适用于套接字。
  • 刚找到这个,boost.org/doc/libs/1_54_0/doc/html/boost_asio/example/cpp03/…,乍一看似乎有超时阻塞读/写:)

标签: c++ boost cross-platform boost-asio


【解决方案1】:

您可以创建跟踪超时的计时器对象。一种典型的方法是使用异步处理程序创建一个常规计时器。每次触发时,您都会遍历连接对象,以查找未传输任何数据的对象。在您的连接读取处理程序中,您将对象标记为已接收数据。粗略的伪代码:

timer_handler:
  for cnx in connections:
    if cnx.recv_count > 0:
      cnx.recv_count = 0
      cnx.idle_count = 0
      continue

    cnx.idle_count += 1
    if cnx.idle_count > idle_limit:
      cnx.close()


cnx_read_handler:
  cnx.recv_count += 1

注意:我没有使用过 asio,但我确实检查过,似乎提供了计时器。

【讨论】:

    【解决方案2】:

    没有可移植的方式来读取和写入超时的标准输入和输出。

    • Boost.Asio 提供posix::stream_descriptor 以同步和异步读取和写入POSIX 文件描述符,例如标准输入和输出,如posix chat client example 中所示。虽然 Boost.Asio 不支持取消同步操作,但大多数异步操作都可以以可移植的方式取消。与 Boost.Asio Timers 结合的异步操作允许超时:在实体上启动异步操作,设置计时器,如果计时器到期,则在实体上调用 cancel()。有关详细信息,请参阅 Boost.Asio timeout examples
    • Windows 标准句柄不支持通过完成端口的异步 I/O。因此,Boost.Asio 的windows::stream_handle 的文档指出支持命名管道,但不支持匿名管道和控制台流。有几个未回答的问题,例如this 一,关于标准输入和输出句柄的异步 I/O 支持。由于缺乏异步支持,可能需要额外的线程和缓冲来从应用程序中抽象出特定于平台的行为。

    【讨论】:

    • 是的,我已经看过关于截止日期计时器的部分,但我仍然不明白如何将其结合起来以在 BotConnection 类中隐藏所有这些细节。那就是等待/阻塞,直到操作完成或截止时间计时器到期。
    猜你喜欢
    • 1970-01-01
    • 2011-07-31
    • 2011-04-14
    • 1970-01-01
    • 2011-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多