我试图在串行端口上使用boost :: ASIO读取和写入的设备。双方的boost :: ASIO:阅读()和boost :: ASIO :: serial_port :: read_some()块时没有什么阅读。相反,我想检测到这种情况,并写一个命令到该端口来启动该装置。

我要么如何可以检测到没有数据可用?

如果有必要我可以异步做的一切,我只想而如果我能避免额外的复杂性。

有帮助吗?

解决方案

您有几个选择,其实。您可以使用串行端口内置的async_read_some功能,或者您可以使用独立的功能boost::asio::async_read(或async_read_some)。

您还是会碰到,你是有效的情况下“封杀”,因为它们都将调用回调,除非(1)数据已被读取或(2)发生了错误。为了解决这个问题,你需要使用一个deadline_timer对象设置超时。如果超时火灾第一,没有可用数据。否则,你会读出的数据。

在增加的复杂性是不是真的那么坏。您将与两个回调有类似的行为而告终。如果任一“读”或有错误的“超时”回调火灾,你知道这是比赛的失败者。如果任何一个火灾没有错误,那么你知道它的分站冠军(和你应该取消其他呼叫)。在那里你将有你的阻塞调用read_some的地方,你现在有一个呼叫io_svc.run()。你的功能仍然会阻止因为当它调用run之前,但这个时候你控制的持续时间。

下面是一个例子:

void foo()
{
  io_service     io_svc;
  serial_port    ser_port(io_svc, "your string here");
  deadline_timer timeout(io_svc);
  unsigned char  my_buffer[1];
  bool           data_available = false;

  ser_port.async_read_some(boost::asio::buffer(my_buffer),
      boost::bind(&read_callback, boost::ref(data_available), boost::ref(timeout),
                  boost::asio::placeholders::error,
                  boost::asio::placeholders::bytes_transferred));
  timeout.expires_from_now(boost::posix_time::milliseconds(<<your_timeout_here>>));
  timeout.async_wait(boost::bind(&wait_callback, boost::ref(ser_port),
                  boost::asio::placeholders::error));

  io_svc.run();  // will block until async callbacks are finished

  if (!data_available)
  {
    kick_start_the_device();
  }
}

void read_callback(bool& data_available, deadline_timer& timeout, const boost::system::error_code& error, std::size_t bytes_transferred)
{
  if (error || !bytes_transferred)
  {
    // No data was read!
    data_available = false;
    return;
  }

  timeout.cancel();  // will cause wait_callback to fire with an error
  data_available = true;
}

void wait_callback(serial_port& ser_port, const boost::system::error_code& error)
{
  if (error)
  {
    // Data was read and this timeout was canceled
    return;
  }

  ser_port.cancel();  // will cause read_callback to fire with an error
}

这应该让你开始在这里和那里只有一些调整,以满足您的特定需求。我希望这有助于!

另注:没有额外的线程是必要的处理回调。一切都在调用run()内处理。不知道你是否已经意识到了这一点......

其他提示

它实际上是一个很多比答案更简单的在这里已经暗示,你可以同步做到这一点:

假设你的阻塞读是这样的:

size_t len = socket.receive_from(boost::asio::buffer(recv_buf), sender_endpoint);

然后,你将其替换为

socket.non_blocking(true);
size_t len = 0;
error = boost::asio::error::would_block;
while (error == boost::asio::error::would_block)
    //do other things here like go and make coffee
    len = socket.receive_from(boost::asio::buffer(recv_buf), sender_endpoint, 0, error);
std::cout.write(recv_buf.data(), len);

您使用receive_from的替代重载形式几乎所有的发送/接收方法具有。不幸的是,他们采取了标志的说法,但0似乎很好地工作。

您必须ASIO使用免费的功能:: async_read。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top