重新连接设备后 boost::asio::serial_port 读取
我在从 GPS 设备(USB 串行)读取 boost::asio::serial_port 类时遇到问题。 连接设备并从中读取数据工作正常,但是当我断开并重新连接设备时,read_some 不会从端口读取任何字节。
由于 boost 没有检测到串行端口已消失( is_open() 返回 true ),因此当我没有获取数据时,我会定期取消()、关闭()和打开( GPS_PORT )设备,从而重置端口选项在途中。 但这也没有帮助,输入缓冲区保持为空。
我是否遗漏了什么,或者做错了什么,或者这是 asio 中的一个错误? 有没有标准方法来检测端口是否消失?
I have a problem with the boost::asio::serial_port class reading from a GPS device (USB-Serial). Connecting the device and reading from it works fine, but when I disconnect and reconnect the device, read_some doesn't read any bytes from the port.
As boost doesn't seam to detect that the serial port is gone ( is_open() returns true ), I periodically cancel(), close() and open( GPS_PORT ) the device when I don't get data, resetting the port options on the way. But this doesn't help either, the input buffer stays empty.
Am I missing something, or doing something wrong, or is this a bug in asio? Is there a standard way to detect that the port is gone?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
很难说出您的情况的确切原因是什么,但实践表明您经常需要禁用串行端口上的
RTS
敏感性。RTS
是真正的RS-232
接口上的引脚,当另一侧的设备打开时,该引脚就会打开。serial_port::read_some
调用查看此信号的底层Windows API
函数。由于您没有真正的 RS-323 设备,因此您需要依赖该信号的驱动程序模拟,这可能会出现错误(不幸的是经常出现错误)。
要禁用它,请调用
serial_port::set_option(DCB)
,并将RTSControl
设置为RTS_CONTROL_DISABLE
。如果
close()
'ing 您的句柄没有帮助,则可能是boost
出现问题。close()
的源代码如下所示:,即如果
CloseHandle()
由于某种原因失败(或挂起),内部句柄值不会分配给INVALID_HANDLE_VALUE
和is_open()
将始终返回true
。要解决此问题,请在
close()
之后立即检查is_open()
,如果返回true
,则销毁的整个实例>boost::asio::serial_port
并再次创建它。It's hard to say what is the exact reason in your case, but practice shows that you often need to disable
RTS
sensitivity on your serial port.RTS
is a pin on realRS-232
interface that is on when a device on the other side is on.serial_port::read_some
invokes underlyingWindows API
function that looks on this signal.As you don't have the real
RS-323
device, you need to rely on the driver emulation of this signal which may be faulty (and unfortunately often is).To disable it, invoke
serial_port::set_option(DCB)
withRTSControl
set toRTS_CONTROL_DISABLE
.If
close()
'ing your handle doesn't help, it may be a problem withboost
. Source code forclose()
looks like this:, i. e. if
CloseHandle()
fails for some reason (or hangs), the internal handle value is not beign assigned toINVALID_HANDLE_VALUE
andis_open()
will always returntrue
.To work around this, check
is_open()
right afterclose()
'ing, and if it returnstrue
, destroy whole instance ofboost::asio::serial_port
and create it again.通常,当
read_some
无法准备就绪时,您应该会收到boost::system::system_error
类型的异常。 尝试使用read
代替,也许它会返回一个错误,而不仅仅是返回。 您还可以尝试异步方法; 在这种情况下,当设备断开连接时,处理程序应该获得一个错误对象。或者,您可以使用
native()
函数获取端口句柄,并对其调用 ClearCommError()。 它可能会返回错误。Normally you should get an exception of type
boost::system::system_error
whenread_some
cannot ready anymore. Try usingread
instead, maybe it returns an error and doesn't just return. You could also try the async methods; in this case the handler should get an error object when the device was disconnected.Alterantively you could get the handle to the port using the
native()
function and call ClearCommError() on that. It might return the error.尽管 asio
boost::ip:tcp
的处理很容易,但我认为在 Windows 7 上处理 boostserial_port
需要特别小心。我遇到了类似的问题,通过重置
boost::asio::io_service
实例解决了这个问题,io_service_.reset()
。我可以异步读取数据,但第二次尝试时无法执行相同的操作。
其实是read函数本身没有问题,注册异步读失败,导致第二次时boost::asio::io_service::run()立即返回。
我不确定这是否与原始海报有相同的问题,因为我正在使用这些天更新的升压库。
无论如何,这是我的解决方案:
Despite of the easy handling of asio
boost::ip:tcp
, I think handling boostserial_port
requires special caution on Windows 7.I got similar problem and got over it by resetting an instance of
boost::asio::io_service
,io_service_.reset()
.I can read data asynchronously but it fails to do same thing from the second try.
In fact, it was no problem of read function itself, registering asynchronous read failed, which led immediate return from
boost::asio::io_service::run()
in second try.I am not sure this is the same problem as original poster had because I am using newer boost library of these days.
Anyway here is my solution: