![](/img/trans.png)
[英]Boost::asio socket - how to make read_some 'throw' in “timeout”?
[英]How to make a timeout at receiving in boost::asio udp::socket?
我创建了一个单线程应用程序,它通过 UDP 与另一个线程交换。当第二个应用程序断开连接时,我的 socket::receive_from 阻塞了,我不知道如何解决这个问题,而不是将整个程序更改为多线程或异步交互.
我认为接下来可能是一个解决方案:
std::chrono::milliseconds timeout{4};
boost::system::error_code err;
data_t buffer(kPackageMaxSize);
std::size_t size = 0;
const auto status = std::async(std::launch::async,
[&]{
size = socket_.receive_from(boost::asio::buffer(buffer), dst_, 0, err);
}
).wait_for(timeout);
switch (status)
{
case std::future_status::timeout: /*...*/ break;
}
但是我遇到了一个新问题: Qt Creator (GDB 11.1) (我还没有能力尝试一些东西)在我调试时开始下降。 如果它没有运行,解决方案也不总是有效。
附言。 至于“调试时不起作用”,调试(特别是断点)显然会改变时序。 此外,请记住。网络操作具有不同的延迟,并且 UDP 不是有保证的协议:消息可能无法传递。
Asio 代表“异步 IO”。 您可能会怀疑,这意味着异步 IO 是一项内置功能,它是该库的全部目的。 参见 overview/core/async.html: 没有线程的并发
没有必要使std::async
复杂化。 在你的情况下,我建议使用async_receive_from
和use_future
,因为它最接近你选择的 model :
#include <boost/asio.hpp>
#include <iostream>
#include <iomanip>
namespace net = boost::asio;
using net::ip::udp;
using namespace std::chrono_literals;
constexpr auto kPackageMaxSize = 65520;
using data_t = std::vector<char>;
int main() {
net::thread_pool ioc;
udp::socket socket_(ioc, udp::v4());
socket_.bind({{}, 8989});
udp::endpoint ep;
data_t buffer(kPackageMaxSize);
auto fut =
socket_.async_receive_from(net::buffer(buffer), ep, net::use_future);
switch (fut.wait_for(4ms)) {
case std::future_status::ready: {
buffer.resize(fut.get()); // never blocks here
std::cout << "Received " << buffer.size() << " bytes: "
<< std::quoted(
std::string_view(buffer.data(), buffer.size()))
<< "\n";
break;
}
case std::future_status::timeout:
case std::future_status::deferred: {
std::cout << "Timeout\n";
socket_.cancel(); // stop the IO operation
// fut.get() would throw system_error(net::error::operation_aborted)
break;
}
}
ioc.join();
}
大肠杆菌 output:
Received 12 bytes: "Hello World
"
在本地演示超时和成功路径:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.