我有一个类在 Windows 系统上包装了
boost::asio::serial_port
。我用它来启动对提供的缓冲区的异步读取。
在大多数情况下,当我开始
async_read
调用之前队列中有数据时,它效果很好(我尝试使用 https://learn.microsoft.com/en-us/windows/win32/api 进行轮询) /winbase/nf-winbase-clearcommerror 函数)。
但是,当不存在数据时,我的异步调用以 bytes_read = 0 和 error_code = success 完成。
我尝试调试问题,当我执行完全相同的调用,但等待字节到达进行读取时,我读取了所有预期的字节。
是否有任何方法可以发生这种情况并正确记录,或者这可能是一个错误?
这是有问题的函数:
bool stream_channel_serial_device::async_read_bytes(
std::span<uint8_t> buffer,
completion_handler&& handler
)
{
// this is called with a buffer size of 536 bytes
boost::asio::async_read(
serial_port_,
boost::asio::buffer(buffer), // the size of the buffer is 536 bytes
[this,
handler = std::move(handler)]
(boost::system::error_code const& ec, std::size_t bytes_read) {
if (ec) {
// THIS IS NOT TRIGGERED (i.e., ec is success),
// BUT bytes_read is 0!
log_error("Error reading data package: " + ec.message());
}
handler(rx_status{ec, bytes_read});
}
);
return true;
}
请注意: 串口是一个成员变量:
boost::asio::serial_port serial_port_;
此外,串行端口是一个虚拟 com 端口,但这并没有引起任何其他问题(并且确实应该完全模拟 COM 端口)。
我知道我需要读取多少字节
所以告诉Asio:
bool async_read_bytes(std::span<uint8_t> buffer, completion_handler&& handler) {
static constexpr unsigned bytes_to_read = 536; // buffer.size()?
asio::async_read( //
serial_port_, //
asio::buffer(buffer), //
asio::transfer_exactly(bytes_to_read), //
[/*this,*/ handler = std::move(handler)](error_code const& ec, size_t bytes_read) {
if (ec) {
// THIS IS NOT TRIGGERED (i.e., ec is success),
// BUT bytes_read is 0!
log_error("Error reading data package: " + ec.message());
}
handler(rx_status{ec, bytes_read});
});
还有
asio::transfer_at_least
。正如您所知(从评论中),还有 asio::read_until
它有更多选项,不受分隔符序列的限制。参见例如MatchCondition 重载,示例:
代码还存在其他问题,其中一些可能是由于创建问题而复制/粘贴的(缺失/过多
rx_status
)。