База для асинхронного сервера
This commit is contained in:
parent
61eb4ac0ba
commit
f6bfe82e93
33
CMakeLists.txt
Normal file
33
CMakeLists.txt
Normal 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
98
main.cpp
Normal 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
8
src/http_server.cpp
Normal 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
21
src/http_server.h
Normal 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
8
src/listener.cpp
Normal 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
23
src/listener.h
Normal 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
4
src/sdk.h
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <sdkddkver.h>
|
||||||
|
#endif
|
8
src/session.cpp
Normal file
8
src/session.cpp
Normal 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
24
src/session.h
Normal 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
8
src/session_base.cpp
Normal 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
20
src/session_base.h
Normal 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
|
Loading…
x
Reference in New Issue
Block a user