• 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 argccharargv[])
        {
            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;
        }

    主要流程如下:

    1. 通过tcp::socket类定义一个tcp client对象socket
    2. 通过connect函数连接服务器,打开socket连接。
    3. 通过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;
        }

    主要流程如下:

    1. 通过tcp::acceptor创建一个tcp server对象,并绑定端口(也可以不在构造器中自动绑定,而通过bind函数手动绑定)
    2. 通过accept函数获取远端连接
    3. 通过远端连接的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::socketclient)
        {
            time_t now = time(0);
            
    shared_ptr<string> message(new string(ctime(&now)));

            auto callback = [=](const boost::system::error_codeerr ,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::acceptorserver)
        {
            
    shared_ptr<tcp::socket> client(new tcp::socket(server.get_io_service()));
            accept_callback callback = [&server, client](const boost::system::error_codeerror)
                {
                    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来实现的自动释放。

    更多的示例请参看asio官方文档

  • 相关阅读:
    2019-8-31-C#-标准性能测试高级用法
    2018-8-29-Roslyn-通过-Target-修改编译的文件
    2018-8-29-Roslyn-通过-Target-修改编译的文件
    2018-2-13-图论-Warshall-和Floyd-矩阵传递闭包
    2018-2-13-图论-Warshall-和Floyd-矩阵传递闭包
    2019-10-26-Inno-Setup-安装包脚本-Run-的-Flags-标记
    netfilter
    mmap内存映射
    vim替换字符串
    vim环境配置
  • 原文地址:https://www.cnblogs.com/lidabo/p/3786184.html
Copyright © 2020-2023  润新知