boost async_accept 不使用 boost asio use_future 选项
boost async_accept not working with the boost asio use_future option
我想在 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
...
回答您的要求:
"future object and the asynchronous accept function aren't communicating" -- 不可能。
"the client is able to connect, but I still get a timeout.", -- 您的客户端连接到侦听器是一个事件,执行 completion-handler(设置 promise)是另一个事件。
因此连接可能在第 9 秒接受,回调将安排在第 11 秒 运行(例如)。
请记住,我们正在处理异步操作,因此我认为对未来事件进行绝对预测是不正确的。
除了
// 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 最近的编辑扩展我的答案:
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();
}
在你的程序中有很多事情需要注意(避免不必要的 spin-loop,不要忘记加入或分离 std::thread
并确保你调用 io_service::run
当你使用 async*
版本时)
Start
Connected to server
future is ready
Accepted a connection
0
Finish
我想在 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
...
回答您的要求:
"future object and the asynchronous accept function aren't communicating" -- 不可能。
"the client is able to connect, but I still get a timeout.", -- 您的客户端连接到侦听器是一个事件,执行 completion-handler(设置 promise)是另一个事件。
因此连接可能在第 9 秒接受,回调将安排在第 11 秒 运行(例如)。
请记住,我们正在处理异步操作,因此我认为对未来事件进行绝对预测是不正确的。
除了
// 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 最近的编辑扩展我的答案:
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();
}
在你的程序中有很多事情需要注意(避免不必要的 spin-loop,不要忘记加入或分离 std::thread
并确保你调用 io_service::run
当你使用 async*
版本时)
Start
Connected to server
future is ready
Accepted a connection
0
Finish