База для асинхронного сервера

This commit is contained in:
Sithas777 2023-09-13 15:20:40 +03:00
parent 61eb4ac0ba
commit f6bfe82e93
11 changed files with 255 additions and 0 deletions

33
CMakeLists.txt Normal file
View File

@ -0,0 +1,33 @@
cmake_minimum_required(VERSION 3.11)
project(HelloAsync CXX)
set(CMAKE_CXX_STANDARD 20)
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_MULTITHREADED ON)
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "/home/oem/Libs/boost/1.82.0/include")
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "/home/oem/Libs/boost/1.82.0/lib")
#include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
# conan_basic_setup()
find_package(Boost 1.78.0 REQUIRED)
if(Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
endif()
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
add_executable(hello_async
main.cpp
src/http_server.cpp
src/http_server.h
src/session.h
src/session.cpp
src/session_base.h
src/session_base.cpp
src/listener.h
src/listener.cpp
src/sdk.h)
target_link_libraries(hello_async PRIVATE Threads::Threads)

98
main.cpp Normal file
View File

@ -0,0 +1,98 @@
#include "src/sdk.h"
//
#include <boost/asio/signal_set.hpp>
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>
#include "src/http_server.h"
namespace
{
namespace net = boost::asio;
using namespace std::literals;
namespace sys = boost::system;
namespace http = boost::beast::http;
// Запрос, тело которого представлено в виде строки
using StringRequest = http::request<http::string_body>;
// Ответ, тело которого представлено в виде строки
using StringResponse = http::response<http::string_body>;
struct ContentType
{
ContentType() = delete;
constexpr static std::string_view
TEXT_HTML = "text/html"sv;
// При необходимости внутрь ContentType можно добавить и другие типы контента
};
// Создаёт StringResponse с заданными параметрами
StringResponse MakeStringResponse(http::status status, std::string_view body, unsigned http_version,
bool keep_alive,
std::string_view content_type = ContentType::TEXT_HTML)
{
StringResponse response(status, http_version);
response.set(http::field::content_type, content_type);
response.body() = body;
response.content_length(body.size());
response.keep_alive(keep_alive);
return response;
}
StringResponse HandleRequest(StringRequest&& req)
{
// Подставьте сюда код из синхронной версии HTTP-сервера
return MakeStringResponse(http::status::ok, "OK"sv, req.version(), req.keep_alive());
}
// Запускает функцию fn на n потоках, включая текущий
template<typename Fn>
void RunWorkers(unsigned n, const Fn& fn)
{
n = std::max(1u, n);
std::vector<std::jthread> workers;
workers.reserve(n - 1);
// Запускаем n-1 рабочих потоков, выполняющих функцию fn
while (--n)
{
workers.emplace_back(fn);
}
fn();
}
} // namespace
int main()
{
const unsigned num_threads = std::thread::hardware_concurrency();
net::io_context ioc(num_threads);
// Подписываемся на сигналы и при их получении завершаем работу сервера
net::signal_set signals(ioc, SIGINT, SIGTERM);
signals.async_wait([&ioc](const sys::error_code& ec, [[maybe_unused]] int signal_number)
{
if (!ec)
{
ioc.stop();
}
});
const auto address = net::ip::make_address("0.0.0.0");
constexpr
net::ip::port_type port = 8080;
http_server::ServeHttp(ioc, {address, port}, [](auto&& req, auto&& sender)
{
// sender(HandleRequest(std::forward<decltype(req)>(req)));
});
// Эта надпись сообщает тестам о том, что сервер запущен и готов обрабатывать запросы
std::cout << "Server has started..."sv << std::endl;
RunWorkers(num_threads, [&ioc]
{
ioc.run();
});
}

8
src/http_server.cpp Normal file
View File

@ -0,0 +1,8 @@
#include "http_server.h"
#include <boost/asio/dispatch.hpp>
#include <iostream>
namespace http_server
{
}

21
src/http_server.h Normal file
View File

@ -0,0 +1,21 @@
#pragma once
#include "sdk.h"
// boost.beast будет использовать std::string_view вместо boost::string_view
#define BOOST_BEAST_USE_STD_STRING_VIEW
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/strand.hpp>
#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include "listener.h"
#include "session.h"
namespace http_server
{
template<typename RequestHandler>
void ServeHttp(net::io_context& ioc, const tcp::endpoint& endpoint, RequestHandler&& handler)
{
// Напишите недостающий код, используя информацию из урока
}
}

8
src/listener.cpp Normal file
View File

@ -0,0 +1,8 @@
#include "http_server.h"
#include <boost/asio/dispatch.hpp>
#include <iostream>
namespace http_server
{
} // namespace http_server

23
src/listener.h Normal file
View File

@ -0,0 +1,23 @@
#pragma once
#include "sdk.h"
// boost.beast будет использовать std::string_view вместо boost::string_view
#define BOOST_BEAST_USE_STD_STRING_VIEW
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/strand.hpp>
#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
namespace http_server
{
namespace net = boost::asio;
using tcp = net::ip::tcp;
namespace beast = boost::beast;
namespace http = beast::http;
template<typename RequestHandler>
class Listener : public std::enable_shared_from_this<Listener<RequestHandler>>
{
// Напишите недостающий код, используя информацию из урока
};
} // namespace http_server

4
src/sdk.h Normal file
View File

@ -0,0 +1,4 @@
#pragma once
#ifdef WIN32
#include <sdkddkver.h>
#endif

8
src/session.cpp Normal file
View File

@ -0,0 +1,8 @@
#include "http_server.h"
#include <boost/asio/dispatch.hpp>
#include <iostream>
namespace http_server
{
} // namespace http_server

24
src/session.h Normal file
View File

@ -0,0 +1,24 @@
#pragma once
#include "sdk.h"
// boost.beast будет использовать std::string_view вместо boost::string_view
#define BOOST_BEAST_USE_STD_STRING_VIEW
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/strand.hpp>
#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include "session_base.h"
namespace http_server {
namespace net = boost::asio;
using tcp = net::ip::tcp;
namespace beast = boost::beast;
namespace http = beast::http;
template <typename RequestHandler>
class Session : public SessionBase, public std::enable_shared_from_this<Session<RequestHandler>> {
// Напишите недостающий код, используя информацию из урока
};
} // namespace http_server

8
src/session_base.cpp Normal file
View File

@ -0,0 +1,8 @@
#include "http_server.h"
#include <boost/asio/dispatch.hpp>
#include <iostream>
namespace http_server
{
} // namespace http_server

20
src/session_base.h Normal file
View File

@ -0,0 +1,20 @@
#pragma once
#include "sdk.h"
// boost.beast будет использовать std::string_view вместо boost::string_view
#define BOOST_BEAST_USE_STD_STRING_VIEW
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/strand.hpp>
#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
namespace http_server {
namespace net = boost::asio;
using tcp = net::ip::tcp;
namespace beast = boost::beast;
namespace http = beast::http;
class SessionBase {
// Напишите недостающий код, используя информацию из урока
};
} // namespace http_server