Boost asio 串口在 async_read 上提前完成

问题描述 投票:0回答:1

我有一个类在 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 端口)。

c++ boost asio
1个回答
0
投票

我知道我需要读取多少字节

所以告诉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
)。

© www.soinside.com 2019 - 2024. All rights reserved.