AsyncReadStream& stream,
DynamicBuffer& buffer,
basic_parser< isRequest >& parser,
ReadHandler&& handler = net::default_completion_token_t< executor_type< AsyncReadStream > >{});
根据上述内容,我是否在下面的异步读取中遗漏了一些内容?因为没有 抛出了重载函数错误的实例
void hook::connector(std::string id){
boost::system::error_code ec;
auto stream_socket=std::make_shared<boost::beast::tcp_stream>(boost::asio::make_strand(ioc));
boost::beast::flat_buffer read_buffer;
boost::beast::http::request<boost::beast::http::string_body> con_req;
boost::beast::http::response<boost::beast::http::string_body> con_res;
boost::asio::ip::tcp::endpoint endP = this->select_endP(servers[id].endpoint_pool, servers[id].domain);
stream_socket->expires_after(std::chrono::seconds(30));
try {
stream_socket->async_connect(endP, [this, id, stream_socket,&read_buffer,con_req, con_res](boost::system::error_code ec) {
if (!ec) {
std::cout << "Connected to server!" << std::endl;
stream_socket->expires_after(std::chrono::seconds(30));
boost::beast::http::async_write(*stream_socket,con_req,
[this, id, stream_socket,&read_buffer,con_req,con_res](boost::system::error_code ec, std::size_t bytes_transferred) {
boost::ignore_unused(bytes_transferred);
if (!ec) {
read_buffer.clear();
//error is being raised from this snippet
boost::beast::http::async_read(*stream_socket,read_buffer,con_res,[this,id,con_res](boost::system::error_code ec,std::size_t transfered_size){
boost::ignore_unused(transfered_size);
if(!ec){
//success
} else{
//failure
};
});
if (con_req.need_eof()) {
boost::beast::error_code shutdown_ec;
stream_socket->socket().shutdown(boost::asio::ip::tcp::socket::shutdown_send, shutdown_ec);
if(shutdown_ec) {
cout << "Error shutting down: " << shutdown_ec.message() << endl;
}
};
} else {
std::cout << "Error writing: " << ec.message() << std::endl;
// Retry the connection on failure
}
}
);
} else {
std::cout << "Error connecting: " << ec.message() << std::endl;
// Retry the connection on failure
}
});
} catch (const std::exception& e) {
std::cout << "Error with read and write: " << e.what() << std::endl;
}
};
您正在通过不可变的 lambda 表达式按值捕获多个对象。除了这没有做你需要的事情之外,这还意味着对象是
const
(不可变)。
这就是为什么
con_res
不能与 async_read
一起使用:它无法转换为对消息对象(或解析器)的可变引用。
“修复”编译器错误的一种偶然方法是使 lambda 可变:
Live On Compiler Explorer(两者都耗尽了资源)
#include <boost/asio.hpp>
#include <boost/beast.hpp>
#include <iostream>
#include <map>
namespace asio = boost::asio;
namespace beast = boost::beast;
namespace http = beast::http;
using asio::ip::tcp;
struct hook {
void connector(std::string id);
asio::io_context ioc;
struct Server {
std::string domain;
std::vector<tcp::endpoint> endpoint_pool;
};
std::map<std::string, Server> servers{
{"test",
Server{
"www.google.com",
{
{tcp::endpoint{{}, 8989}},
{tcp::endpoint{{}, 9090}},
{tcp::endpoint{{}, 9191}},
},
}},
};
tcp::endpoint select_endP(std::vector<tcp::endpoint> const& endpoint_pool, std::string /*domain*/) {
return endpoint_pool[0]; // TODO: implement selection logic
}
};
void hook::connector(std::string id) {
boost::system::error_code ec;
auto stream_socket = std::make_shared<beast::tcp_stream>(make_strand(ioc));
beast::flat_buffer read_buffer;
http::request<http::string_body> con_req;
http::response<http::string_body> con_res;
tcp::endpoint endP = this->select_endP(servers[id].endpoint_pool, servers[id].domain);
stream_socket->expires_after(std::chrono::seconds(30));
try {
stream_socket->async_connect(
endP, [this, id, stream_socket, &read_buffer, con_req, con_res](boost::system::error_code ec) {
if (!ec) {
std::cout << "Connected to server!" << std::endl;
stream_socket->expires_after(std::chrono::seconds(30));
http::async_write(
*stream_socket, con_req,
[this, id, stream_socket, &read_buffer, con_req,
con_res](beast::error_code ec, std::size_t bytes_transferred) mutable {
boost::ignore_unused(bytes_transferred);
if (!ec) {
read_buffer.clear();
// error is being raised from this snippet
http::async_read(
*stream_socket, read_buffer, con_res,
[this, id /*, con_res*/](beast::error_code ec,
std::size_t transfered_size) mutable {
boost::ignore_unused(transfered_size);
if (!ec) {
// success
} else {
// failure
};
});
if (con_req.need_eof()) {
beast::error_code shutdown_ec;
stream_socket->socket().shutdown(tcp::socket::shutdown_send, shutdown_ec);
if (shutdown_ec) {
std::cout << "Error shutting down: " << shutdown_ec.message()
<< std::endl;
}
};
} else {
std::cout << "Error writing: " << ec.message() << std::endl;
// Retry the connection on failure
}
});
} else {
std::cout << "Error connecting: " << ec.message() << std::endl;
// Retry the connection on failure
}
});
} catch (std::exception const& e) {
std::cout << "Error with read and write: " << e.what() << std::endl;
}
};
int main() {
hook h;
h.connector("test");
}
然而,实际上,您最终总是会得到
con_req
和 con_res
的空副本。您真正想要的是共享这些内容。例如:
住在科里鲁
#include <boost/asio.hpp>
#include <boost/beast.hpp>
#include <iostream>
#include <map>
namespace asio = boost::asio;
namespace beast = boost::beast;
namespace http = beast::http;
using asio::ip::tcp;
struct hook {
void connector(std::string id);
asio::thread_pool ioc;
struct Server {
std::string domain;
std::vector<tcp::endpoint> endpoint_pool;
};
std::map<std::string, Server> servers{
{"test",
Server{
"www.google.com",
{
{tcp::endpoint{{}, 8989}},
{tcp::endpoint{{}, 9090}},
{tcp::endpoint{{}, 9191}},
},
}},
};
tcp::endpoint select_endP(std::vector<tcp::endpoint> const& endpoint_pool, std::string /*domain*/) {
return endpoint_pool[0]; // TODO: implement selection logic
}
};
void hook::connector(std::string id) {
struct Con {
beast::tcp_stream stream_socket;
std::string id;
beast::flat_buffer read_buffer = {};
http::request<http::string_body> con_req= {};
http::response<http::string_body> con_res = {};
};
auto state = std::make_shared<Con>(Con{beast::tcp_stream{make_strand(ioc)}, id});
tcp::endpoint endP = this->select_endP(servers[id].endpoint_pool, servers[id].domain);
state->stream_socket.expires_after(std::chrono::seconds(30));
try {
state->stream_socket.async_connect(
endP, [state, id](boost::system::error_code ec) {
if (!ec) {
std::cout << "Connected to server!" << std::endl;
state->stream_socket.expires_after(std::chrono::seconds(30));
http::async_write(
state->stream_socket, state->con_req,
[id, state](beast::error_code ec, size_t bytes_transferred) mutable {
boost::ignore_unused(bytes_transferred);
if (!ec) {
state->read_buffer.clear();
// error is being raised from this snippet
http::async_read(
state->stream_socket, state->read_buffer, state->con_res,
[state, id](beast::error_code ec, size_t transfered_size) mutable {
boost::ignore_unused(transfered_size);
if (!ec) {
// success
} else {
// failure
};
});
if (state->con_req.need_eof()) {
beast::error_code shutdown_ec;
state->stream_socket.socket().shutdown(tcp::socket::shutdown_send,
shutdown_ec);
if (shutdown_ec) {
std::cout << "Error shutting down: " << shutdown_ec.message()
<< std::endl;
}
};
} else {
std::cout << "Error writing: " << ec.message() << std::endl;
// Retry the connection on failure
}
});
} else {
std::cout << "Error connecting: " << ec.message() << std::endl;
// Retry the connection on failure
}
});
} catch (std::exception const& e) {
std::cout << "Error with read and write: " << e.what() << std::endl;
}
};
int main() {
hook h;
h.connector("test");
}
当然,正如您已经意识到的那样(因为您捕获了
this
),将操作作为 Con
类的一部分更有意义。