首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >boost async_accept不能与boost asio use_future选项一起使用

boost async_accept不能与boost asio use_future选项一起使用
EN

Stack Overflow用户
提问于 2019-06-16 11:05:24
回答 1查看 575关注 0票数 1

我想在超时的情况下听boost::asio::ip::tcp::socket。为此,我使用了std::future::wait_for函数。下面是我的代码:

代码语言:javascript
复制
std::optional<boost::asio::ip::tcp::socket> server::listen()
{
    boost::asio::ip::tcp::socket sock(io_service);
    std::future<void> accept_status = acceptor.async_accept(
        sock, boost::asio::use_future);
    if (accept_status.wait_for(std::chrono::seconds(10)) == std::future_status::timeout)
    {
        // I hope there's no race-condition between
        // accepting a connection and calling cancel
        acceptor.cancel();
        std::cerr << "Timeout" << std::endl;
        return {};
    }
    std::cerr << "Accepted a connection" << std::endl;
    return {std::move(sock)};
}

但这不起作用:客户端可以连接,但我仍然超时。这意味着将来的对象和异步接受函数不会通信。我遗漏了什么?

我正在使用Boost版本的1.65

对于Explorer_N,以下是一个完整的程序,它的工作方式与我预期的不同:

代码语言:javascript
复制
#include <boost/asio.hpp>
#include <boost/asio/use_future.hpp>
#include <chrono>
#include <future>
#include <iostream>
#include <thread>

using namespace std;

void server_listen() {
    boost::asio::io_service io_service;
    boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), 31132);
    boost::asio::ip::tcp::acceptor acceptor(io_service, endpoint);
    boost::asio::ip::tcp::socket socket(io_service);
    std::future<void> accept_status = acceptor.async_accept(
            socket, boost::asio::use_future);
    while(true) {
        if(accept_status.wait_for(std::chrono::seconds(10)) == std::future_status::timeout) {
            acceptor.cancel();
            std::cerr << "Timeout\n";
        } else {
            break;
        }
    }
    // if I replace the lines starting from the async_accept call
    // by just the following, everything works as expected
    // acceptor.accept(socket);
    std::cout << "Accepted a connection\n";
    while(true) {
    }
}

void client_connect() {
    boost::asio::io_service io_service;
    boost::asio::ip::tcp::resolver resolver(io_service);
    boost::asio::ip::tcp::socket socket(io_service);
    boost::asio::ip::tcp::endpoint endpoint(*resolver.resolve({"127.0.0.1", std::to_string(31132)}));
    socket.connect(endpoint);
    std::cout << "Connected to server\n";
    while(true) {
    }
}

int main() {
    std::thread server(server_listen);
    std::this_thread::sleep_for(std::chrono::seconds(2));
    std::thread client(client_connect);
    while(true) {
    }
}

g++ -std=c++17 <program>.cpp -lpthread -lboost_system -o <program>编译。

我得到的输出是:

代码语言:javascript
复制
Connected to server
Timeout
Timeout
Timeout
Timeout
Timeout
Timeout
Timeout
Timeout
Timeout
Timeout
Timeout
Timeout
Timeout
...
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-06-24 16:36:47

要回答您的申请,请执行以下操作:

“未来的对象和异步接受函数无法通信”--这是不可能的。

“客户端能够连接,但我仍然获得超时。”,--您的客户端连接到侦听器是一个事件,而执行完成处理程序(设置promise)是另一个事件。

因此,连接可以在第9秒接受,而回调将安排在第11秒运行(例如)。

请记住,我们正在处理异步操作,因此对未来事件进行绝对预测是不正确的。

除此之外,

代码语言:javascript
复制
// I hope there's no race-condition between
        // accepting a connection and calling cancel
        acceptor.cancel();
        std::cerr << "Timeout" << std::endl;
        return {};

acceptor.cancel();只是收集挂起的等待程序,并在ec设置为operation_aborted的情况下完成它们,如果处理程序已经到达完成事件队列,那么cancel()就是一个no-op

根据OP最近的编辑扩展我的答案:

代码语言:javascript
复制
using namespace std;

void server_listen() {
    boost::asio::io_service io_service;
    boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), 31132);
    boost::asio::ip::tcp::acceptor acceptor(io_service, endpoint);
    boost::asio::ip::tcp::socket socket(io_service);
    auto work = make_work_guard(io_service);
    using type= std::decay_t<decltype(work)>;
    std::thread io([&](){io_service.run();});
    std::future<void> accept_status = acceptor.async_accept(
            socket, boost::asio::use_future);
    if(accept_status.wait_for(std::chrono::seconds(10)) == std::future_status::timeout) {
        acceptor.cancel();
        std::cerr << "Timeout\n";
        work.~type();
        //break;
    } else {
        std::cout<<"future is ready\n";
        work.~type();
       // break;
    }

    io.join();
    // if I replace the lines starting from the async_accept call
    // by just the following, everything works as expected
    // acceptor.accept(socket);
    std::cout << "Accepted a connection\n";

}

void client_connect() {
    boost::asio::io_service io_service;
    boost::asio::ip::tcp::resolver resolver(io_service);
    boost::asio::ip::tcp::socket socket(io_service);
    boost::asio::ip::tcp::endpoint endpoint(*resolver.resolve({"127.0.0.1", std::to_string(31132)}));
    socket.connect(endpoint);
    std::cout << "Connected to server\n";

}
enter code here
int main() {
    std::thread server(server_listen);
    std::this_thread::sleep_for(std::chrono::seconds(2));
    std::thread client(client_connect);
    server.join(); client.join();
}

在你的程序中有许多事情需要注意(避免不必要的自旋循环,不要忘记加入或分离std::thread,并确保在使用async*版本时调用io_service::run )

代码语言:javascript
复制
Start
Connected to server
future is ready
Accepted a connection
0
Finish
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56615760

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档