Skip to content

Instantly share code, notes, and snippets.

@BluBb-mADe
Last active August 4, 2023 19:32
Show Gist options
  • Save BluBb-mADe/2bf6e8f203256273adbf4ef113474428 to your computer and use it in GitHub Desktop.
Save BluBb-mADe/2bf6e8f203256273adbf4ef113474428 to your computer and use it in GitHub Desktop.
Simple c++20 coroutine boost beast websocket echo server example
#include <exception>
#include <iostream>
#include <coroutine>
#include <string_view>
#include <chrono>
#include <boost/asio.hpp>
#include <boost/beast.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/iostreams/stream.hpp>
namespace asio = boost::asio;
namespace beast = boost::beast;
namespace websocket = beast::websocket;
using tcp = asio::ip::tcp;
using namespace std::literals;
asio::awaitable<void> echo(auto ws) {
beast::flat_buffer buffer;
try {
for (;;) {
co_await ws.async_read(buffer, asio::use_awaitable);
co_await ws.async_write(buffer.data(), asio::use_awaitable);
buffer.clear();
}
}
catch(boost::system::system_error& e) {}
if (ws.is_open()) {
co_await ws.async_close(websocket::close_code::normal, asio::as_tuple(asio::use_awaitable));
}
}
asio::awaitable<void> listener() {
auto exec = co_await asio::this_coro::executor;
tcp::acceptor acceptor(exec, {asio::ip::make_address("0.0.0.0"), 8085});
while (acceptor.is_open()) {
auto [ec, socket] = co_await acceptor.async_accept(asio::as_tuple(asio::use_awaitable));
if (ec) continue;
socket.set_option(tcp::no_delay{ true });
socket.set_option(asio::socket_base::keep_alive{ false });
websocket::stream<tcp::socket, false> ws(std::move(socket));
ws.read_message_max(8);
ws.set_option(
websocket::stream_base::timeout{
2s, // handshake
2s, // idle
true // timeout during close frame exchange
});
ws.binary(true);
auto [ec2] = co_await ws.async_accept(asio::as_tuple(asio::use_awaitable));
if (ec2) continue;
asio::co_spawn(exec, echo(std::move(ws)), asio::detached);
}
}
int main() {
constexpr int thread_count = 4;
asio::io_context io_ctx(thread_count);
asio::signal_set signals(io_ctx, SIGINT, SIGTERM);
signals.async_wait([&io_ctx](auto, auto) { io_ctx.stop(); });
asio::co_spawn(io_ctx, listener(), asio::detached);
std::vector<std::jthread> threads;
for (auto i = 0; i < thread_count - 1; ++i) {
threads.emplace_back([&io_ctx] { io_ctx.run(); });
}
io_ctx.run();
std::cout << "bye bye";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment