我想听一个带有超时的boost::asio::ip::tcp::socket
。为此,我正在使用std::future::wait_for
函数。下面是我的代码:
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
,以下是一个完整的程序,该程序无法按我期望的方式工作:#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>
编译。我得到的输出是:
Connected to server
Timeout
Timeout
Timeout
Timeout
Timeout
Timeout
Timeout
Timeout
Timeout
Timeout
Timeout
Timeout
Timeout
...
最佳答案
回答您的要求:
“将来的对象和异步接受函数无法通信”-不可能。
“客户端可以连接,但是我仍然会超时。”,-您的客户端连接到监听器是一个事件,执行完成处理程序(设置Promise)是另一个事件。
因此,连接可以在第9秒接受,而回调将排定在第11秒运行(例如)。
记住,我们正在处理异步操作,因此对 future 事件进行绝对预测并不是我想说的。
分开的形式
// 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()是一个空操作根据OP的最新编辑来扩展我的答案:
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
并确保在使用io_service::run
版本时调用async*
)Start
Connected to server
future is ready
Accepted a connection
0
Finish
关于sockets - boost async_accept无法与boost asio use_future选项一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56615760/