this is what my fileCollector looks like, it just stores a "cache" of files (so that you don't read the file during each request)
class FileCollector
{
public:
FileCollector();
std::string get_file_data(std::string s);
private:
std::map<std::string, std::string> fileData;
};
The error is most likely here, but due to inexperience I can't find it.
http_connection::http_connection(tcp::socket socket, std::shared_ptr<Collector::FileCollector> fc)
: socket_(std::move(socket)),
filecollector(fc)
{}
void http_connection::start(void)
{
read_request();
}
void http_connection::read_request(void)
{
auto self = shared_from_this();
http::async_read(
socket_,
buffer_,
request_,
[self](beast::error_code ec,
std::size_t bytes_transferred)
{
boost::ignore_unused(bytes_transferred);
if(!ec)
self->process_request();
}
);
}
void http_connection::process_request(void)
{
response_.version(request_.version());
response_.keep_alive(false);
switch (request_.method())
{
case (http::verb::get):
response_.result(http::status::ok);
response_.set(http::field::server, "Beast");
create_response();
break;
default:
response_.result(http::status::bad_request);
response_.set(http::field::content_type, "text/plain");
beast::ostream(response_.body())
<< "Invalid request-method '"
<< std::string(request_.method_string())
<< "'";
break;
}
write_response();
}
void http_connection::create_response(void)
{
std::string_view sv = request_.target().substr(1);
std::string targetfile = {sv.data(), sv.size()};
beast::ostream(response_.body())
<< filecollector->get_file_data(targetfile);
}
void http_connection::write_response(void)
{
auto self = shared_from_this();
response_.content_length(response_.body().size());
http::async_write(
socket_,
response_,
[self](beast::error_code er, std::size_t bytes_trans)
{
self->socket_.shutdown(tcp::socket::shutdown_send, er);
}
);
}
the way I start connections
void ownHTTPServer::start_acceptor(tcp::acceptor& accepter, tcp::socket& sock,
std::shared_ptr<Collector::FileCollector> &fc)
{
accepter.async_accept(sock,
[&](beast::error_code er){
if (!er)
{
std::make_shared<ownHTTPServer::http_connection>
(std::move(sock), std::move(fc))->start();
}
start_acceptor(accepter, sock, fc);
});
}
g++ -IC:\boost\include\boost-1_84 -lws2_32 -lwsock32 ... compliler x86_64-w64-mingw32
the code works if you don't use filecollector and the response content is const char*
If it's not difficult for someone, I would like to read articles on how boost.asio works
In
start_acceptor(), each time a new client is accepted, you are creating a newhttp_connectionobject and moving (not sharing) ownership of yourshared_ptr<FileCollector> fcobject into that connection:Thus,
fcloses access to theFileCollectorobject in memory, making it unavailable when subsequent connections transferfcagain and again.You should not be using
std::move()to transfer ownership of astd::shared_ptr, that defeats the whole point of using shared ownership.Your
http_connectionconstructor takes theshared_ptrby value, as it should. So, simply do not usestd::move()when passingfcto that constructor, letfcbe copied so theFileCollectorobject is properly shared across multipleshared_ptrinstances:Along those same lines, you should also be capturing
fcby value, not by reference (just as you do withselfinhttp_connection::read_request()), eg:That way, the
FileCollectorobject is shared properly while theasync_accept()handler is waiting to be called.