Initial commit

This commit is contained in:
Артём Кокос
2026-01-26 21:22:56 +07:00
commit b670e17670
7 changed files with 1394 additions and 0 deletions

85
.clang-format Normal file
View File

@@ -0,0 +1,85 @@
AccessModifierOffset: -2
AlignAfterOpenBracket: AlwaysBreak
AlignConsecutiveMacros: false
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: DontAlign
AlignOperands: false
AlignTrailingComments: false
AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: false
BinPackParameters: false
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeBraces: Attach
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: AfterColon
BreakInheritanceList: AfterColon
BreakStringLiterals: false
ColumnLimit: 80
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
FixNamespaceComments: true
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^<ext/.*\.h>'
Priority: 2
SortPriority: 0
CaseSensitive: false
- Regex: '^<.*\.h>'
Priority: 1
SortPriority: 0
CaseSensitive: false
- Regex: '^<.*'
Priority: 2
SortPriority: 0
CaseSensitive: false
- Regex: '.*'
Priority: 3
SortPriority: 0
CaseSensitive: false
IncludeIsMainRegex: '([-_](test|unittest))?$'
IndentCaseLabels: true
IndentPPDirectives: BeforeHash
IndentWidth: 4
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: false
MaxEmptyLinesToKeep: 1
NamespaceIndentation: Inner
PointerAlignment: Left
ReflowComments: false
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: true
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: false
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 4
UseTab: Never

4
Makefile Normal file
View File

@@ -0,0 +1,4 @@
build-md:
nvim --headless -c "execute 'Neorg export to-file TUTORIAL.md' | sleep 100m | q" norg/tutorial.norg
markdown-toc -i TUTORIAL.md
nvim --headless -c "execute 'Neorg export to-file README.md' | sleep 100m | q" norg/readme.norg

26
README.md Normal file
View File

@@ -0,0 +1,26 @@
# 📚 Boost.Asio: Асинхронность в C++
Руководство по созданию клиент-серверных систем с помощью C++, библиотек Boost.Asio и Boost.Beast.
<h1 align="center">
[ЧИТАТЬ ОНЛАЙН](./TUTORIAL.md)
</h1>
<div align="center">
Руководство находится в стадии перевода
</div>
# 💡 О руководстве
Это руководство является вольным переводом [серии туториалов](https://dens.website/tutorials/cpp-asio). Поскольку перевод вольный, в нем могут быть некоторые отступления от изначального текста.
# 🎈 Помощь в переводе
В переводе могут быть некоторые неточности, которые неправильно преподносят суть тех или иных вещей. Если вы нашли подобную неточность, откройте Issue или создайте Pull Request. Спасибо!

1073
TUTORIAL.md Normal file

File diff suppressed because it is too large Load Diff

19
code/simple_server.cpp Normal file
View File

@@ -0,0 +1,19 @@
#include <boost/asio.hpp>
int main() {
std::uint16_t port = 15001;
boost::asio::io_context io_context;
boost::asio::ip::udp::endpoint receiver(boost::asio::ip::udp::v4(), port);
boost::asio::ip::udp::socket socket(io_context, receiver);
while (true) {
char buffer[65536];
boost::asio::ip::udp::endpoint sender;
std::size_t bytes_transferred =
socket.receive_from(boost::asio::buffer(buffer), sender);
socket.send_to(boost::asio::buffer(buffer, bytes_transferred), sender);
}
return 0;
}

56
code/tcp_async_server.cpp Normal file
View File

@@ -0,0 +1,56 @@
#include <boost/asio.hpp>
#include <iostream>
#include <optional>
class session: public std::enable_shared_from_this<session> {
public:
session(boost::asio::ip::tcp::socket&& socket) :
socket(std::move(socket)) {}
void start() {
boost::asio::async_read_until(
socket,
streambuf,
'\n',
[self = shared_from_this()](
boost::system::error_code error,
std::size_t bytes_transferred) {
std::cout << std::istream(&self->streambuf).rdbuf();
});
}
private:
boost::asio::ip::tcp::socket socket;
boost::asio::streambuf streambuf;
};
class server {
public:
server(boost::asio::io_context& io_context, std::uint16_t port) :
io_context(io_context),
acceptor(
io_context,
boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)) {}
void async_accept() {
socket.emplace(io_context);
acceptor.async_accept(*socket, [&](boost::system::error_code error) {
std::make_shared<session>(std::move(*socket))->start();
async_accept();
});
}
private:
boost::asio::io_context& io_context;
boost::asio::ip::tcp::acceptor acceptor;
std::optional<boost::asio::ip::tcp::socket> socket;
};
int main() {
boost::asio::io_context io_context;
server srv(io_context, 15001);
srv.async_accept();
io_context.run();
return 0;
}

131
code/tcp_chat_server.cpp Normal file
View File

@@ -0,0 +1,131 @@
#include <boost/asio.hpp>
#include <optional>
#include <queue>
#include <unordered_set>
namespace io = boost::asio;
using tcp = io::ip::tcp;
using error_code = boost::system::error_code;
using namespace std::placeholders;
using message_handler = std::function<void(std::string)>;
using error_handler = std::function<void()>;
class session: public std::enable_shared_from_this<session> {
public:
session(tcp::socket&& socket) : socket(std::move(socket)) {}
void start(message_handler&& on_message, error_handler&& on_error) {
this->on_message = std::move(on_message);
this->on_error = std::move(on_error);
async_read();
}
void post(const std::string& message) {
bool idle = outgoing.empty();
outgoing.push(message);
if (idle) {
async_write();
}
}
private:
void async_read() {
io::async_read_until(
socket,
streambuf,
"\n",
std::bind(&session::on_read, shared_from_this(), _1, _2));
}
void on_read(error_code error, std::size_t bytes_transferred) {
if (!error) {
std::stringstream message;
message << socket.remote_endpoint(error) << ": "
<< std::istream(&streambuf).rdbuf();
streambuf.consume(bytes_transferred);
on_message(message.str());
async_read();
} else {
socket.close(error);
on_error();
}
}
void async_write() {
io::async_write(
socket,
io::buffer(outgoing.front()),
std::bind(&session::on_write, shared_from_this(), _1, _2));
}
void on_write(error_code error, std::size_t bytes_transferred) {
if (!error) {
outgoing.pop();
if (!outgoing.empty()) {
async_write();
}
} else {
socket.close(error);
on_error();
}
}
tcp::socket socket;
io::streambuf streambuf;
std::queue<std::string> outgoing;
message_handler on_message;
error_handler on_error;
};
class server {
public:
server(io::io_context& io_context, std::uint16_t port) :
io_context(io_context),
acceptor(io_context, tcp::endpoint(tcp::v4(), port)) {}
void async_accept() {
socket.emplace(io_context);
acceptor.async_accept(*socket, [&](error_code error) {
auto client = std::make_shared<session>(std::move(*socket));
client->post("Welcome to chat\n\r");
post("We have a newcomer\n\r");
clients.insert(client);
client->start(
std::bind(&server::post, this, _1),
[&, weak = std::weak_ptr(client)] {
if (auto shared = weak.lock();
shared && clients.erase(shared)) {
post("We are one less\n\r");
}
});
async_accept();
});
}
void post(const std::string& message) {
for (auto& client : clients) {
client->post(message);
}
}
private:
io::io_context& io_context;
tcp::acceptor acceptor;
std::optional<tcp::socket> socket;
std::unordered_set<std::shared_ptr<session>> clients;
};
int main() {
io::io_context io_context;
server srv(io_context, 15001);
srv.async_accept();
io_context.run();
return 0;
}