/http-server

A http server implemented using asio library.

Primary LanguageCMIT LicenseMIT

http-server

基于asio的高性能http/websocket服务器,支持Windows和Linux

  • 接口简单易用
    #include "http/server.hpp"
    http::server server{8080, 8}; //8 threads

    server.get("/hello", [](const http::request &) {
        http::response res;
        res.status = http::status_type::ok; //200
        res.content.emplace<std::string>("<h1>Hello world!</h1>");
        return res;
    });

    //协程作为回调函数
    server.get("/login", [](const http::request &req) -> http::task<http::response>{//C++标准要求,协程必须显式指定返回类型。
        http::response res;
        auto session = co_await /*数据库操作*/
        ...
        co_return res;
    });

    //正则表达式
    server.get("/.*\\.html", [](const http::request &req) -> http::task<http::response> {
        http::response res;
        res.status = http::status_type::ok;
        res.headers.insert({"Content-Type", "text/html"});
        res.content.emplace<std::filesystem::path>(std::string{R"(../public)"} + req.url);
        co_return res;
    });

    //websocket
    server.websocket("/echo", [ ](http::ws_stream stream)->http::task<void> {
        while (true) {
            std::string msg;
            boost::asio::dynamic_string_buffer buffer{ msg, 1 << 16 };
            std::tuple<boost::system::error_code> ret = co_await stream.async_read(buffer);
            if (std::get<0>(ret))
                co_return;
            stream.send(std::make_shared<std::string>(std::move(msg))); 
        }
    });

    //subscribe-publish
    server.websocket("/chat-room", [ ](http::ws_stream stream)->http::task<void> {
        stream.join("chat"); //join in a room named "chat"
        while (true) {
            auto msg = std::make_shared<std::string>();
            msg->reserve(128);
            boost::asio::dynamic_string_buffer buffer{ *msg, 1 << 16 };
            auto ret = co_await stream.async_read(buffer);
            if(std::get<0>(ret))
                co_return;     //automatic call stream.leave() to leave room
            /*
             *  deal with message
             */
            stream.room().publish(msg);
        }
    });


    server.listen();
  • 高性能:使用 IOCPio_uring,小文件传输 1万 QPS,速率 1.2 GB /s,大文件传输速率高达 2 GB /s
Server Software:
Server Hostname: 127.0.0.1
Server Port: 8080
Document Path: /girl.jpeg
Document Length: 119513 bytes
Concurrency Level: 100
Time taken for tests: 9.576 seconds
Complete requests: 100000
Failed requests: 0
Total transferred: 11955800000 bytes
HTML transferred: 11951300000 bytes
Requests per second: 10442.85
Transfer rate: 1219264.17 kB/s received
Connection Times (ms)
  min avg max
Connect: 0 0 10
Processing: 6 9 216
Total: 6 9 226
Server Software:
Server Hostname:127.0.0.1
Server Port:8080
Document Path:/girl.mp4
Document Length:11165483 bytes
Concurrency Level:10
Time taken for tests:4.964 seconds
Complete requests:1000
Failed requests:0
Total transferred:11165527000 bytes
HTML transferred:11165483000 bytes
Requests per second:201.44
Transfer rate:2196434.60 kB/s received
Connection Times (ms)
  min avg max
Connect: 0 0 2
Processing: 42 49 66
Total: 42 49 68

Build

Linux 下依赖liburing,内核版本5.15以上, 低于5.15使用epoll和线程池(文件IO)

git clone https://github.com/axboe/liburing.git
cd liburing
./configure
make install

CMakeLists.txt

cmake_minimum_required(VERSION 3.20)
project(yourproject)

set(CMAKE_CXX_STANDARD 20) #支持协程

find_package(Boost 1.80.0 REQUIRED)        #依赖boost库,Linux下要求v1.78以上(io_uring)
include_directories(${Boost_INCLUDE_DIR})

add_subdirectory(http)

add_executable(yourproject ...)
target_link_libraries(yourproject http) 
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make
./http-server

测试

http://localhost:8080/index.html

benchmark

ab -n 1000 -c 10 http://127.0.0.1/girl.mp4