簡體   English   中英

如何在接收 boost::asio udp::socket 時超時?

[英]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_fromuse_future ,因為它最接近你選擇的 model :

生活在 Coliru

#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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM