09-Daytime.4-A synchronous UDP daytime client

本教程程序展示了如何使用asio实现一个基于UDP的客户端应用。

#include <asio.hpp>

#include <spdlog/spdlog.h>

using asio::ip::udp;

int main(int argc, char* argv[])
{
    // 应用程序的启动与TCP daytime客户端基本相同。
    try {
        if (argc != 2) {
            spdlog::error("Usage: {} port", argv[0]);
            return 1;
        }

        asio::io_context io_context;

        // 我们使用一个ip::udp::resolver对象,根据主机名和服务名查找要使用的正确远程端点。
        // 通过ip::udp::v4()参数限制查询仅返回IPv4端点。
        udp::resolver resolver(io_context);
        udp::endpoint receiver_endpoint = *resolver.resolve(udp::v4(), argv[1], "daytime").begin();

        // ip::udp::resolver::resolve()函数保证在未失败的情况下,返回的列表中至少包含一个端点。
        // 这意味着可以直接解引用返回值,这是安全的操作。  
        //
        // 由于UDP是面向数据报的协议,我们不会使用流式套接字。
        // 请创建一个ip::udp::socket并与远程端点建立连接。
        udp::socket socket(io_context);
        socket.open(udp::v4());

        std::array<char, 1> send_buf = { { 0 } };
        socket.send_to(asio::buffer(send_buf), receiver_endpoint);

        // 现在我们需要准备好接收服务器发回的任何数据。
        // 我们这边接收服务器响应的端点将通过ip::udp::socket::receive_from()进行初始化。
        std::array<char, 128> recv_buf;
        udp::endpoint sender_endpoint;
        size_t len = socket.receive_from(asio::buffer(recv_buf), sender_endpoint);
        spdlog::info("Received {} bytes from {}: {}",
             len, 
             sender_endpoint.address().to_string(), 
             recv_buf.data());
    } catch (const std::exception& e) {
        spdlog::error("Exception: {}", e.what());
        return 1;
    }
}