08-Daytime.3-An asynchronous TCP daytime server

// tcp_server.h
#pragma once

#include <asio.hpp>

#include <memory>
#include <string>

using asio::ip::tcp;

inline std::string make_daytime_string()
{
    using namespace std; // For time_t, time and ctime;
    time_t now = time(0);
    return ctime(&now);
}

class tcp_connection
    // 我们将使用 shared_ptr 和 enable_shared_from_this,
    // 因为我们希望在仍有操作引用 tcp_connection 对象时保持其存活状态。
    : public std::enable_shared_from_this<tcp_connection> {
public:
    typedef std::shared_ptr<tcp_connection> pointer;

    static pointer create(asio::io_context& io_context)
    {
        return pointer(new tcp_connection(io_context));
    }

    tcp::socket& socket()
    {
        return socket_;
    }

    // 在函数start()中,我们调用asio::async_write()向客户端发送数据。
    // 请注意,这里使用的是asio::async_write()而非ip::tcp::socket::async_write_some(),以确保整个数据块被完整发送。
    void start()
    {
        // 要发送的数据存储在类成员message_中,因为我们需要保持数据有效,直到异步操作完成。
        message_ = make_daytime_string();

        // 在启动异步操作时,如果使用std::bind,必须只指定与处理程序参数列表匹配的参数。
        // 在本程序中,两个参数占位符(asio::placeholders::error和asio::placeholders::bytes_transferred)都可能被移除,
        // 因为它们并未在handle_write()中使用。
        asio::async_write(socket_, asio::buffer(message_),
            std::bind(&tcp_connection::handle_write, shared_from_this(),
                asio::placeholders::error,
                asio::placeholders::bytes_transferred));
        //此客户端连接的后续操作现在由handle_write()负责处理。
    }

private:
    tcp_connection(asio::io_context& io_context)
        : socket_(io_context)
    {
    }

    void handle_write(const std::error_code& /*error*/,
        size_t /*bytes_transferred*/)
    {
    }

    tcp::socket socket_;
    std::string message_;
};

class tcp_server {
public:
    tcp_server(asio::io_context& io_context)
        : io_context_(io_context)
        // 构造函数初始化一个接收器,监听tcp::v4()地址的13端口
        , acceptor_(io_context, tcp::endpoint(tcp::v4(), 13))
    {
        start_accept();
    }

private:
// 该函数创建一个socket,同时初始化一个异步接受操作,等待客户端连接
    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));
    }

    // 该函数会在初始化的异步接受操作完成后被调用
    // 该函数响应客户端请求,然后调用start_accept()函数,开始下一次接受操作
    void handle_accept(tcp_connection::pointer new_connection,
        const std::error_code& error)
    {
        if (!error) {
            new_connection->start();
        }

        start_accept();
    }

    asio::io_context& io_context_;
    tcp::acceptor acceptor_;
};

运行效果与之前的相同,只是一个是同步,一个是异步。