使用无栈协程实现的单线程HTTP服务器

Boost.Asio源码解读(三)——使用无栈协程实现的单线程HTTP服务器

模型优势

可以类似用符合思维习惯的同步手法,写出具有异步功能的高效代码,而不用像传统异步开发设置各种回调函数把代码割离弄的支离破碎的;最后还是得意于协程比线程更加的轻量级,切换过程也不会陷入内核态,增加系统的运行效率。

主要的类

在这里插入图片描述

重要实现

  • server重载operator()

官方代码代码地址

https://www.boost.org/doc/libs/1_71_0/doc/html/boost_asio/examples/cpp03_examples.html

简化后的代码如下

客户端

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

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

enum {
    max_length = 1024
};

int main(int argc, char *argv[]) {
    try {
        if (argc != 4) {
            std::cerr << "Usage: blocking_tcp_echo_client <host> <port>\n";
            return 1;
        }

        boost::asio::io_context io_context;

        tcp::socket s(io_context);
        tcp::resolver resolver(io_context);
        boost::asio::connect(s, resolver.resolve(argv[1], argv[2]));
        std::string request(argv[3]);
        boost::asio::write(s, boost::asio::buffer(request, request.size()));

        char reply[max_length];
        size_t reply_length = boost::asio::read(s,
                                                boost::asio::buffer(reply, request.size()));
        std::cout << "Reply is: ";
        std::cout.write(reply, reply_length);
        std::cout << "\n";
//        s.close();
    }
    catch (std::exception &e) {
        std::cerr << "Exception: " << e.what() << "\n";
    }

    return 0;
}

服务端

//server.hpp
#include <iostream>
#include <memory>
#include <utility>
#include <boost/asio.hpp>

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

class server : boost::asio::coroutine {
public:
    explicit server(io_context &ioc, int port);

    ~server() = default;

public:
    void operator()(boost::system::error_code ec = boost::system::error_code(), std::size_t length = 0);

private:
    std::shared_ptr<tcp::acceptor> acceptor_;
    std::shared_ptr<tcp::socket> socket_;
    enum {
        length = 1024
    };
    std::shared_ptr<std::array<char, length> > buffer_;
};
//server.cpp
#include <thread>
#include "server.hpp"

server::server(io_context &ioc, int port) {
    boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(),port);
    acceptor_.reset(new tcp::acceptor(ioc, endpoint));
}

#include <boost/asio/yield.hpp>
void server::operator()(boost::system::error_code ec, std::size_t length) {
    if (!ec) {
        reenter(this) {
            do {
                socket_.reset(new tcp::socket(acceptor_->get_executor()));
                yield acceptor_->async_accept(*socket_, *this);
                fork server(*this)();
            } while (is_parent());

            //协程的异步调用也会阻塞比如async_read_some或者async_write中调用阻塞的函数
            buffer_.reset(new std::array<char, 1024>);
            yield socket_->async_read_some(boost::asio::buffer(*buffer_),*this);

            // Send the reply back to the client.
            yield boost::asio::async_write(*socket_, boost::asio::buffer(*buffer_),*this);

            std::clog << buffer_ << std::endl;

            // Initiate graceful connection closure.
            socket_->shutdown(tcp::socket::shutdown_both, ec);
        }
    } else{
        std::clog << "ERROR: "<< ec.message() << std::endl;
    }
}

主函数

#include "server.hpp"

int main(int argc, char *argv[]) {
    try {
        if (argc != 2) {
            std::cerr << "Usage: server <port>\n";
            return 1;
        }
        io_context ioc;
        server(ioc, std::atoi(argv[1]))();

        ioc.run();
    }
    catch (std::exception &e) {
        std::cerr << "Exception: " << e.what() << "\n";
    }

    return 0;
}
发布了80 篇原创文章 · 获赞 68 · 访问量 7543

猜你喜欢

转载自blog.csdn.net/weixin_44048823/article/details/103313857