gpt4 book ai didi

c++ - boost async_read 不使用 ssl 读取所有数据

转载 作者:行者123 更新时间:2023-11-30 05:19:11 26 4
gpt4 key购买 nike

我使用 boost asio 进行网络连接,我注意到当我切换到 ssl 时,我的网络代码不再工作。问题似乎是这里的这一行:

boost::asio::async_read(socket_, boost::asio::buffer(inbound_header_),
boost::bind(&connection::handle_read_header<Handler>,
this, boost::asio::placeholders::error,
boost::make_tuple(handler)));

据我所知,这应该总是在调用处理程序之前读取 inbound_header_.size() 字节。它大部分时间都有效。但有时它只会读取 0 个字节,并且仍然调用错误代码为 0 的处理程序。我做错了什么吗?我从 boost asio 序列化示例中复制了该代码,所以我认为这应该可行。

最小工作样本 here在 Ubuntu 16.04 上使用 boost 1.61.0 测试几乎每次都在启动后的前几秒断言 connection::handle_read_header 被命中。

最佳答案

async_read()将读取直到缓冲区已满或发生错误。如果在这些条件都不满足的情况下调用读取处理程序,那么一个潜在的罪魁祸首是调用了未定义的行为。在这种特殊情况下,代码违反了 boost::asio::ssl:::stream 的线程安全要求。 :

Distinct objects: Safe.

Shared objects: Unsafe. The application must also ensure that all asynchronous operations are performed within the same implicit or explicit strand.

具体来说,写操作是在显式链中执行的(connection::strand_);但是,读取操作是在链外执行的。由于有多个线程运行服务器,程序无法确保所有操作都在同一个链中执行。

void connection::async_write(...)
{
...
// `strand_` protects `message_queue_` and guarantees that writes to
// `socket_` are only occurring within the strand.
strand_.post([...]()
{
auto empty = message_queue_.empty();
message_queue_.push([=]()
{
...
// Intermediate and final handlers are performed within `strand_`.
boost::asio::async_write(socket_, ... strand_.wrap([...](...)
{
...
message_queue_.front()()
}));
});
if (empty)
message_queue_.front()();
});
}

void connection::async_read(...)
{
// Not performed within `strand_`, violating thread safety.
boost::asio::async_read(socket_, ...,
// Neither intermediate, final handler, nor subsequent read
// operations are performed within `strand_`.
[](...)
{
boost::asio::async_read(socket_, ...);
}
});
}

要解决此问题,请从 connection::strand_ 链中显式执行 async_read 操作。此外,操作的读取处理程序也应包含在 connection::strand_ 中:

void connection::async_read(...)
{
strand_.post([...](...)
{
// async_read is now performed with the strand.
boost::asio::async_read(socket_, ...,
// Intermediate and final handlers are performed within the strand.
strand_.wrap([](...)
{
boost::asio::async_read(socket_, ...);
});
});
}

有关如何保证所有异步操作和处理程序在一个链中执行的更多详细信息,请参阅 this回答。

关于c++ - boost async_read 不使用 ssl 读取所有数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41280618/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com