3

我对从 GPS 设备(USB 串行)读取的 boost::asio::serial_port 类有疑问。连接设备并从中读取工作正常,但是当我断开并重新连接设备时,read_some 不会从端口读取任何字节。

由于 boost 无法检测到串行端口已消失( is_open() 返回 true ),因此当我没有获取数据时,我会定期取消()、关闭()和打开( GPS_PORT )设备,重置端口选项在途中。但这也无济于事,输入缓冲区保持为空。

我是否遗漏了什么,或者做错了什么,或者这是 asio 中的错误?有没有标准的方法来检测端口已经消失?

4

3 回答 3

3

很难说您的具体原因是什么,但实践表明您经常需要禁用RTS串行端口的灵敏度。

RTS是真实RS-232接口上的引脚,当另一侧的设备打开时打开。

serial_port::read_some调用查看此信号的底层Windows API函数。

由于您没有真正的RS-323设备,因此您需要依赖此信号的驱动程序仿真,这可能是错误的(不幸的是经常出现)。

要禁用它,请serial_port::set_option(DCB)使用RTSControlset to调用RTS_CONTROL_DISABLE

如果close()你的手柄没有帮助,它可能是一个问题boost。源代码close()如下所示:

  boost::system::error_code close(implementation_type& impl,
      boost::system::error_code& ec)
  {
    if (is_open(impl))
    {
      if (!::CloseHandle(impl.handle_))
      {
        DWORD last_error = ::GetLastError();
        ec = boost::system::error_code(last_error,
            boost::asio::error::get_system_category());
        return ec;
      }

      impl.handle_ = INVALID_HANDLE_VALUE;
      impl.safe_cancellation_thread_id_ = 0;
    }

    ec = boost::system::error_code();
    return ec;
  }

,即如果CloseHandle()由于某种原因失败(或挂起),则内部句柄值不会分配给INVALID_HANDLE_VALUE并且is_open()将始终返回true

要解决这个问题,请在'ingis_open()之后立即检查,如果它返回,则销毁整个实例并再次创建它。close()trueboost::asio::serial_port

于 2009-02-12T12:49:24.603 回答
1

boost::system::system_error通常,当read_some无法再准备好时,您应该获得类型异常。尝试read改用,也许它会返回错误并且不只是返回。您也可以尝试异步方法;在这种情况下,当设备断开连接时,处理程序应该得到一个错误对象。

或者,您可以使用该native()函数获取端口的句柄并在其上调用 ClearCommError()。它可能会返回错误。

于 2009-02-12T12:53:04.737 回答
1

尽管 asio 易于处理,但我认为在 Windows 7 上boost::ip:tcp处理 boost需要特别小心。 我遇到了类似的问题,并通过重置 , 的实例来解决它。 我可以异步读取数据,但在第二次尝试时它没有做同样的事情。 其实是read函数本身没有问题,注册异步读失败,导致第二次try立即返回。serial_port
boost::asio::io_serviceio_service_.reset()

boost::asio::io_service::run()

我不确定这与原始海报是否存在相同的问题,因为我正在使用这些天更新的 boost 库。
无论如何,这是我的解决方案:

// port open step
port_ = boost::shared_ptr<boost::asio::serial_port>
        (new boost::asio::serial_port(io_service_));
boost::thread t(boost::bind(&boost::asio::io_service::run, &io_service_));
port_->async_read_some(....);
.......

// port close step
port_->cancel();
port_->close();
port_.reset();

io_service_.stop();
io_service_.reset();  // <-- IMPORTANT: this makes serial_port works in repeat use.
于 2016-05-26T04:42:59.860 回答