zoukankan      html  css  js  c++  java
  • boost之asio

    asio

    asio是C++的准标准网络库,并且C++20标准库的网络部分将基于ASIO,需引入头文件#include <boost/asio.hpp>

    ip地址

    boost定义了表示ip地址的类型,支持ipv4和ipv6,提供ip::addressip::address_v4以及ip::address_v6三种类型。

    • 通过字符串构造ip地址:
    #include <boost/asio.hpp>
    
    namespace ba = boost::asio;
    namespace bi = ba::ip;
    
    int main(int argc, char* argv[])
    {
        // 通过点分十进制转换为ipv4地址
        bi::address addrV4 = bi::make_address("127.0.0.1");
        assert(addrV4.is_v4());
    
        // 通过十六进制转换为ipv6地址
        bi::address addrV6 = bi::make_address("ABCD:EF01:2345:6789:ABCD:EF01:2345:6789");
        assert(addrV6.is_v6());
    
        // bi::address重载了流操作符,可以直接输出(所以也可以用boost::lexical_cast<string>(address))
        std::cout << addrV4 << std::endl;
        std::cout << addrV6 << std::endl;
    
        return 0;
    }
    

    ip地址+端口

    对于tcp和udp两种协议,定义了对应的类型:ip::tcp::endpointip::udp::endpoint

    • 通过ip地址和端口号构造
    int main(int argc, char* argv[])
    {
        // 端口号直接传入就行,不用转换为网络序
        bi::tcp::endpoint ep(bi::make_address("127.0.0.1"), 1234);
    
        // endpoint也重载了流操作符
        std::cout << ep << std::endl;
    
        return 0;
    }
    

    域名解析

    asio中提供ip::tcp::resolverip::udp::resolver实现域名解析,相当于unix网络编程中的getaddrinfo()接口封装:

    • 解析指定域名和端口对应的ip地址和端口信息:
    int main(int argc, char* argv[])
    {
        // 域名解析需要使用底层网络io
        ba::io_context io;
        bi::tcp::resolver resolver(io);
    
        // 对baidu域名进行解析
        auto endpoints = resolver.resolve("www.baidu.com", "https");
        for (auto& endpoint : endpoints) {
            std::cout << endpoint.endpoint() << std::endl;
        }
    
        return 0;
    }
    

    定时器

    同步模式:

    int main(int argc, char const *argv[])
    {
        ba::io_context io;
        ba::steady_timer tm (io, ba::chrono::seconds(5));
    
        std::cout << "start timer" << std::endl;
        tm.wait();
        std::cout << "end wait" << std::endl;
    
        return 0;
    }
    

    异步模式:

    int main(int argc, char const *argv[])
    {
        ba::io_context io;
        ba::steady_timer tm (io, ba::chrono::seconds(5));
    
        tm.async_wait([] (boost::system::error_code ec) {
            std::cout << "time's up" << std::endl;
        });
    
        io.run();
    
        return 0;
    }
    

    周期定时器:

    void heartbeat(std::shared_ptr<ba::steady_timer> tm, boost::system::error_code ec) {
        std::cout << "heart beat" << std::endl;
        tm->expires_after(ba::chrono::seconds(1));
        tm->async_wait([tm] (boost::system::error_code ec) {
            heartbeat(tm, ec);
        });
    }
    
    int main(int argc, char const *argv[])
    {
        ba::io_context io;
        auto tm = std::make_shared<ba::steady_timer>(io, ba::chrono::seconds(1));
    
        tm->async_wait([tm] (boost::system::error_code ec) {
            heartbeat(tm, ec);
        });
    
        io.run();
    
        return 0;
    }
    

    buffer

    asio使用的是proactor模式,也就是io操作不光是通知有了可读可写事件,并且会将可读写到调用者指定的buffer中,从调用者指定的buffer中取数据写入,所以asio提供了数据缓冲类型。
    有两种buffer:mutable_bufferconst_buffer,buffer并不申请内存,它只是一个内存块的封装,本质上就一个void *data,size_t size的一个数据对,所以需要确保引用数据的生命周期。
    buffer函数用于创建mutable_bufferconst_buffer对象,支持POD数组,PODarray,PODvectorstring类型:

    #include <iostream>
    #include <string>
    #include <boost/asio.hpp>
    
    namespace ba = boost::asio;
    
    int main(int argc, char const *argv[])
    {
        (void)argc;
        (void)argv;
    
        std::string str = "123";
        ba::mutable_buffer mbuf = ba::buffer(str);
        const std::string cstr = "123";
        ba::const_buffer cbuf = ba::buffer(cstr);
    
        std::cout << mbuf.size() << std::endl;
        std::cout << cbuf.size() << std::endl;
    
        return 0;
    }
    

    同步模式tcp客户端和服务端

    以下是asio教程中关于daytime服务的tcp客户端和服务端代码:

    #include <iostream>
    #include <string>
    #include <array>
    #include <boost/asio.hpp>
    
    namespace ba = boost::asio;
    namespace bi = ba::ip;
    
    int main(int argc, char const *argv[])
    {
        (void)argc;
        (void)argv;
    
        ba::io_context io;
        bi::tcp::resolver resolver(io);
        auto endpoints = resolver.resolve("localhost", "daytime");
        bi::tcp::socket connSocket(io);
        ba::connect(connSocket, endpoints);
    
        std::array<char, 128> arr;
        while (true) {
            boost::system::error_code ec;
            size_t len = connSocket.read_some(ba::buffer(arr), ec);
            if (ba::error::eof == ec) {
                break;
            } else if (ec) {
                throw boost::system::system_error(ec);
            }
            std::cout.write(arr.data(), len);
        }
    
        return 0;
    }
    
    #include <iostream>
    #include <string>
    #include <array>
    #include <ctime>
    #include <boost/asio.hpp>
    
    namespace ba = boost::asio;
    namespace bi = ba::ip;
    
    int main(int argc, char const *argv[])
    {
        (void)argc;
        (void)argv;
    
        ba::io_context io;
        bi::tcp::acceptor acceptor(io, bi::tcp::endpoint(bi::tcp::v4(), 13));
    
        while (true) {
            bi::tcp::socket connSocket(io);
            acceptor.accept(connSocket);
            time_t now = time(0);
            std::string message = ctime(&now);
            ba::write(connSocket, ba::buffer(message));
        }
    
        return 0;
    }
    
  • 相关阅读:
    Spring学习02——控制反转、依赖注入
    Spring学习01——HelloSpring
    $(function() {})和$(document).ready(function(){ })
    tomcat 学习
    XML学习
    使用git提交项目至github的标准步骤
    Bootstrap快速入门
    HashMap底层原理及面试问题 [更新中]
    ArrayList remove()元素遇到的问题
    linux 给指定用户分配文件夹权限
  • 原文地址:https://www.cnblogs.com/HachikoT/p/13795967.html
Copyright © 2011-2022 走看看