12-Daytime.7-A combined TCP and UDP asynchronous server
#include <array>
#include <ctime>
#include <functional>
#include <memory>
#include <asio.hpp>
#include <spdlog/spdlog.h>
using asio::ip::tcp;
using asio::ip::udp;
std::string make_daytime_string()
{
using namespace std;
time_t now = time(nullptr);
return ctime(&now);
}
class tcp_connection
: public std::enable_shared_from_this<tcp_connection> {
public:
using pointer = std::shared_ptr<tcp_connection>;
static pointer create(asio::io_context& io)
{
return pointer(new tcp_connection(io));
}
tcp::socket& socket()
{
return socket_;
}
void start()
{
auto message = make_daytime_string();
asio::async_write(socket_, asio::buffer(message),
std::bind(&tcp_connection::handle_write, shared_from_this()));
}
private:
tcp_connection(asio::io_context& io)
: socket_(io)
{
spdlog::info("tcp_connection created at {}", make_daytime_string());
}
void handle_write() { }
private:
tcp::socket socket_;
std::string message_;
};
class tcp_server {
public:
tcp_server(asio::io_context& io_context)
: io_context_(io_context)
, acceptor_(io_context, tcp::endpoint(tcp::v4(), 13))
{
start_accept();
}
private:
void start_accept()
{
tcp_connection::pointer new_connection = tcp_connection::create(io_context_);
acceptor_.async_accept(new_connection->socket(),
std::bind(&tcp_server::handle_accept,
this, new_connection, asio::placeholders::error));
}
void handle_accept(tcp_connection::pointer new_connection,
const std::error_code& error)
{
if (!error) {
new_connection->start();
}
start_accept();
}
private:
asio::io_context& io_context_;
tcp::acceptor acceptor_;
};
class udp_server {
public:
udp_server(asio::io_context& io_context)
: socket_(io_context, udp::endpoint(udp::v4(), 13))
{
start_receive();
}
private:
void start_receive()
{
socket_.async_receive_from(
asio::buffer(recv_buffer_),
remote_endpoint_,
std::bind(&udp_server::handle_receive,
this, asio::placeholders::error));
}
void handle_receive(const std::error_code& error)
{
if (!error) {
std::shared_ptr<std::string> message(new std::string(make_daytime_string()));
socket_.async_send_to(
asio::buffer(*message),
remote_endpoint_,
std::bind(&udp_server::handle_send, this, message));
start_receive();
}
}
void handle_send(std::shared_ptr<std::string> message)
{
}
private:
udp::socket socket_;
udp::endpoint remote_endpoint_;
std::array<char, 1> recv_buffer_;
};
int main()
{
try {
asio::io_context io;
tcp_server tcp_server_(io);
udp_server udp_server_(io);
io.run();
} catch (const std::exception& e) {
spdlog::error("Exception: {}", e.what());
}
}