boost.asio框架系列之socket编程

 更新时间:2022年06月18日 15:36:07   作者:天方  
这篇文章介绍了boost.asio框架系列之socket编程,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

asio的主要用途还是用于socket编程,本文就以一个tcp的daytimer服务为例简单的演示一下如何实现同步和异步的tcp socket编程。

客户端

客户端的代码如下:

    #include <iostream>
    #include <boost/array.hpp>
    #include <boost/asio.hpp>

    using boost::asio::ip::tcp;

    int main(int argc, char* argv[])
    {
        try
        {
            boost::asio::io_service io_service;
            tcp::endpoint end_point(boost::asio::ip::address::from_string("127.0.0.1"), 3200);

            tcp::socketsocket(io_service);
            socket.connect(end_point);

            for (;;)
            {
                boost::array<char, 128> buf;
                boost::system::error_code error;

                size_t len = socket.read_some(boost::asio::buffer(buf), error);

                if (error == boost::asio::error::eof)
                    break; // Connection closed cleanly by peer.
                else if (error)
                    throw boost::system::system_error(error); // Some other error.

                std::cout.write(buf.data(), len);
            }
        }
        catch (std::exception& e)
        {
            std::cerr << e.what() << std::endl;
        }

        return 0;
    }

主要流程如下:

  • 通过tcp::socket类定义一个tcp client对象socket

  • 通过connect函数连接服务器,打开socket连接。

  • 通过read_some函数来读数据

另外,还可以通过write_some来写数据,通过close来关闭socket连接(这里是通过释放socket对象隐式释放连接)。

服务器

服务器代码如下:

    #include <ctime>
    #include <iostream>
    #include <string>
    #include <boost/asio.hpp>

    using namespace boost;
    using boost::asio::ip::tcp;

    int main()
    {
        try
        {
            asio::io_service io_service;
            tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 3200));

            for (;;)
            {
                tcp::socket socket(io_service);
                acceptor.accept(socket);

                time_t now = time(0);
                std::string message = ctime(&now);

                system::error_code ignored_error;
                socket.write_some(asio::buffer(message), ignored_error);
            }
        }
        catch (std::exception& e)
        {
            std::cerr << e.what() << std::endl;
        }

        return 0;
    }

主要流程如下:

  • 通过tcp::acceptor类创建一个tcp server对象,并绑定端口(也可以不在构造器中自动绑定,而通过bind函数手动绑定)

  • 通过accept函数获取远端连接

  • 通过远端连接的write_some函数将数据发往客户端

异步服务器

前面的服务器是同步版本,在大并发的场景下一般需要用到异步socket。服务器的异步版本如下:

    #include <ctime>
    #include <iostream>
    #include <string>
    #include <memory>
    #include <functional>
    #include <boost/asio.hpp>

    using boost::asio::ip::tcp;
    using namespace std;

    void process_client(shared_ptr<tcp::socket> client)
    {
        time_t now = time(0);
        shared_ptr<string> message(new string(ctime(&now)));

        auto callback = [=](const boost::system::error_code& err ,size_t size)
        {
            if ((int)size == message->length())
                cout << "write completed" << endl;
        };

        client->async_send(boost::asio::buffer(*message), callback);
    }

    typedef function<void (const boost::system::error_code&)> accept_callback;
    void start_accept(tcp::acceptor& server)
    {
        shared_ptr<tcp::socket> client(new tcp::socket(server.get_io_service()));
        accept_callback callback = [&server, client](const boost::system::error_code& error)
            {
                if (!error)
                    process_client(client);

                start_accept(server);
            };

        server.async_accept(*client, callback);
    }

    int main()
    {
        try
        {
            boost::asio::io_service io_service;
            tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 3200));
            start_accept(acceptor);
            io_service.run();
        }
        catch (std::exception& e)
        {
            std::cerr << e.what() << std::endl;
        }
        return 0;
    }

这个异步版本的逻辑倒不是很复杂,基本上和.net中传统的异步socket相似,不过需要注意的是,由于c++中内存需要自己管理,而asio框架也没有提供任何管理机制,因此需要注意async_accept、async_send等函数的参数生命周期,切记不能在里面传入栈变量的引用。如果是堆变量,需要确保释放,本例中我是通过share_ptr来实现的自动释放。

到此这篇关于boost.asio框架系列之socket编程的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • C语言 数据结构与算法之字符串详解

    C语言 数据结构与算法之字符串详解

    这篇文章将带大家深入了解C语言数据结构与算法中的字符串,文中主要是介绍了字符串的定义、字符串的比较以及一些串的抽象数据类型,感兴趣的可以学习一下
    2022-01-01
  • C++中函数模板的用法详细解析

    C++中函数模板的用法详细解析

    所谓函数模板实际上是建立一个通用函数,其涵涵素类型额形参类型不具体指定,用一个虚拟的类型来代表,这个通用函数就称为函数模板
    2013-10-10
  • Opencv实现绿幕视频背景替换功能

    Opencv实现绿幕视频背景替换功能

    这篇文章主要为大家详细介绍了Opencv实现绿幕视频背景替换功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-05-05
  • 数据结构与算法中二叉树子结构的详解

    数据结构与算法中二叉树子结构的详解

    这篇文章主要介绍了数据结构与算法中二叉树子结构的详解的相关资料,需要的朋友可以参考下
    2017-04-04
  • C++实现LeetCode(904.水果装入果篮)

    C++实现LeetCode(904.水果装入果篮)

    这篇文章主要介绍了C++实现LeetCode(904.水果装入果篮),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • Unity3D实现经典小游戏Pacman

    Unity3D实现经典小游戏Pacman

    这篇文章主要介绍了基于Unity3D制作一做个经典小游戏Pacman,文中的示例代码讲解详细,对我们学习Unity3D有一定的帮助,感兴趣的小伙伴可以了解一下
    2021-12-12
  • C++面经之什么是RAII面试问题解析

    C++面经之什么是RAII面试问题解析

    这篇文章主要介绍了C++面经之什么是RAII面试问题解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-06-06
  • C/C++ 获取Windows系统的位数32位或64位的实现代码

    C/C++ 获取Windows系统的位数32位或64位的实现代码

    这篇文章主要介绍了C/C++ 获取Windows系统的位数32位或64位的实现代码的相关资料,希望通过本文能帮助到大家,让大家实现这样的功能,需要的朋友可以参考下
    2017-10-10
  • C语言实现三子棋程序

    C语言实现三子棋程序

    这篇文章主要为大家详细介绍了C语言实现三子棋程序,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-03-03
  • 深入解析C++中的引用类型

    深入解析C++中的引用类型

    引用指的是对一个对象的引用。那么什么是对象?在c++中狭义的对象指的是用类,结构,联合等复杂数据类型来声明的变量,如 MyClass myclass,CDialog mydlg,等等
    2013-09-09

最新评论