重新连接Device后,boost :: asio :: serial_port读取

时间:2009-02-12 12:37:07

标签: c++ boost serial-port boost-asio

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

由于boost没有接缝检测到串口消失(is_open()返回true),我在没有获取数据时定期取消(),关闭()并打开(GPS_PORT)设备,重置途中的港口选择。但这也无济于事,输入缓冲区保持空白。

我错过了什么,或做错了什么,或者这是asio中的错误?有没有一种标准的方法可以检测到端口消失了?

3 个答案:

答案 0 :(得分:3)

很难说出你的确切原因是什么,但是练习表明你经常需要在串口上禁用RTS灵敏度。

RTS是真实RS-232接口上的一个引脚,当另一侧的设备开启时,该接口处于打开状态。

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

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

要禁用它,请在serial_port::set_option(DCB)设置为RTSControl的情况下调用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

要解决此问题,请在is_open()之后立即检查close(),如果它返回true,则销毁boost::asio::serial_port的整个实例并重新创建。

答案 1 :(得分:1)

通常,当boost::system::system_error无法再准备就绪时,您应该获得read_some类型的例外情况。尝试使用read代替,也许它会返回错误并且不会返回。您也可以尝试异步方法;在这种情况下,处理程序应在设备断开连接时获取错误对象。

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

答案 2 :(得分:1)

尽管asio boost::ip:tcp易于处理,但我认为处理提升serial_port需要特别注意Windows 7。 我遇到了类似的问题,通过重置boost::asio::io_service io_service_.reset()的实例来克服它。
我可以异步读取数据,但是第二次尝试时却无法做同样的事情 实际上,读取函数本身并没有问题,注册异步读取失败,导致第二次尝试从boost::asio::io_service::run()立即返回。

我不确定这是与原版海报相同的问题,因为我现在正在使用更新的升级库 无论如何,这是我的解决方案:

// 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.