基于uWebSockets开源库实现一个web服务

一.uWebSockets简介

uWebSockets 是一款用 C++ 编写的高性能 Web 服务器库,专注于实时通信‌。它支持 WebSocket、HTTP/1.1 和 HTTP/2 协议,专为高并发、低延迟的实时应用设计‌.

核心特性
极致性能‌:基于异步 I/O 和事件驱动架构,单进程可处理数万并发连接,平均延迟低于 1ms‌。
低内存占用‌:通过内存池技术减少动态内存分配,适合大规模部署‌。
跨平台支持‌:兼容 Linux、Windows 等操作系统‌。
轻量级设计‌:直接处理 WebSocket 协议,避免多进程/线程的开销‌。
典型应用场景
高频交易系统‌:如订单实时推送‌。
物联网网关‌:设备状态同步‌。
在线多人游戏‌:实时动作广播‌。

与其他库对比
相较于 Node.js 和 Nginx,uWebSockets 在应用层直接处理协议,性能更优‌。其源码结构清晰,包含核心代码、示例程序和性能测试模块‌。

二.linux下uWebSockets编译

编译步骤
1.获取源代码‌
使用git克隆uWebSockets的主仓库

git clone https://github.com/uNetworking/uWebSockets.git
cd uWebSockets

2.处理依赖的子模块‌
uWebSockets依赖uSockets和libdeflate两个第三方库,需要手动下载并编译它们.

3.编译uWebSockets‌
在uWebSockets根目录下执行
 

三.qt下实现一个web服务

1)在.pro文件中添加uWebSockets依赖文件及依赖库

httpServer.pro内容如下:



QT -= gui
 
CONFIG += c++17 console
CONFIG -= app_bundle
 
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
 
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
 
SOURCES += 
        main.cpp
 
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
 
unix:!macx: LIBS += -L$$PWD/3rdparty/uSockets/lib/ -luSockets
 
INCLUDEPATH += $$PWD/3rdparty/uSockets/include
DEPENDPATH += $$PWD/3rdparty/uSockets/include
 
unix:!macx: PRE_TARGETDEPS += $$PWD/3rdparty/uSockets/lib/libuSockets.a
 
unix:!macx: LIBS += -L$$PWD/3rdparty/libdeflate/lib/ -ldeflate
 
INCLUDEPATH += $$PWD/3rdparty/libdeflate/include
DEPENDPATH += $$PWD/3rdparty/libdeflate/include
 
unix:!macx: PRE_TARGETDEPS += $$PWD/3rdparty/libdeflate/lib/libdeflate.a
 
LIBS += -lz -lssl
 
HEADERS += 
    helpers/AsyncFileReader.h 
    helpers/AsyncFileStreamer.h 
    helpers/Middleware.h 
    helpers/optparse.h 
    httphandle.h 
    src/App.h 
    src/AsyncSocket.h 
    src/AsyncSocketData.h 
    src/BloomFilter.h 
    src/CachingApp.h 
    src/ChunkedEncoding.h 
    src/ClientApp.h 
    src/Http3App.h 
    src/Http3Context.h 
    src/Http3ContextData.h 
    src/Http3Request.h 
    src/Http3Response.h 
    src/Http3ResponseData.h 
    src/HttpContext.h 
    src/HttpContextData.h 
    src/HttpErrors.h 
    src/HttpParser.h 
    src/HttpResponse.h 
    src/HttpResponseData.h 
    src/HttpRouter.h 
    src/LocalCluster.h 
    src/Loop.h 
    src/LoopData.h 
    src/MessageParser.h 
    src/MoveOnlyFunction.h 
    src/Multipart.h 
    src/PerMessageDeflate.h 
    src/ProxyParser.h 
    src/QueryParser.h 
    src/TopicTree.h 
    src/Utilities.h 
    src/WebSocket.h 
    src/WebSocketContext.h 
    src/WebSocketContextData.h 
    src/WebSocketData.h 
    src/WebSocketExtensions.h 
    src/WebSocketHandshake.h 
    src/WebSocketProtocol.h

2)main()函数实现

main.cpp内容如下:



#include <QCoreApplication>
#include "src/App.h"
 
/* Helpers for this example */
#include "helpers/AsyncFileReader.h"
#include "helpers/AsyncFileStreamer.h"
#include "helpers/Middleware.h"
 
#define OPTPARSE_IMPLEMENTATION
#include "helpers/optparse.h"
 
#include "httphandle.h"
int main(int argc, char *argv[])
{
 
    int port = 9999;
    uWS::SocketContextOptions ssl_options =
    {
        .key_file_name = "misc/key.pem",
        .cert_file_name = "misc/cert.pem",
        .passphrase = "1234"
    };
 
 
    std::string root = "public";
    AsyncFileStreamer asyncFileStreamer(root);
 
    /* Either serve over HTTP or HTTPS */
#if 1
    {
        /* HTTPS */
        uWS::SSLApp(ssl_options).get("/*", [&asyncFileStreamer](auto *res, auto *req) {
            ServeFile(res,req);
        }).post("/*", [&asyncFileStreamer](auto *res, auto *req) {
            ServeFile(res,req);
        }).listen(port, [port, root](auto *token) {
            if (token) {
                std::cout << "Serving " << root << " over HTTPS a " << port << std::endl;
            }
        }).run();
    }
#else
    {
        /* HTTP */
        uWS::App().get("/*", [&asyncFileStreamer](auto *res, auto *req) {
            ServeFile(res,req);
        }).post("/*", [&asyncFileStreamer](auto *res, auto *req) {
            ServeFile(res,req);
        }).listen(port, [port, root](auto *token) {
            if (token) {
                std::cout << "Serving " << root << " over HTTP a " << port << std::endl;
            }
        }).run();
    }
#endif
    std::cout << "Failed to listen to port " << port << std::endl;
    return 0;
}

3)ServeFile()函数实现



template <bool SSL>
uWS::HttpResponse<SSL> *ServeFile(uWS::HttpResponse<SSL> *res, uWS::HttpRequest *req)
{
    printRequestInfo(res,req);
    res->writeStatus(uWS::HTTP_200_OK);
    res->writeHeader("Content-Type", "text/plain; charset=gbk");
 
    std::string reqStr = std::string(req->getUrl());
    std::string response;
    if(reqStr == "/login"){
        response = Login();
    }else if(reqStr == "/getNetworkInfo"){
        response = GetNetworkInfo();
    }else if(reqStr == "/sysManage/setSystemInfo"){
        response = SetSystemInfo(req);
    }else if(reqStr == "/sysManage/setCurTime"){
        response = SetCurTime(req);
    }else{
        response = "no defined api.";
    }
 
    res->end(response);
    return res;
}

4)printRequestInfo()函数实现



std::map<std::string, std::string> parseFormData(const std::string& body)
{
    std::map<std::string, std::string> params;
 
    std::istringstream iss(body);
    std::string pair;
 
    while (std::getline(iss, pair, '&')) {
        size_t pos = pair.find('=');
        if (pos != std::string::npos) {
            std::string key = pair.substr(0, pos);
            std::string value = pair.substr(pos + 1);
            params[key] = value;
        }
    }
 
    return params;
}
/**
     * 打印HttpRequest的基本信息
     * @param req 指向HttpRequest对象的指针
     */
template <bool SSL>
static void printRequestInfo(uWS::HttpResponse<SSL> *res,uWS::HttpRequest *req) {
    if (!req) {
        std::cout << "Request pointer is null" << std::endl;
        return;
    }
    // 创建缓冲区,存储累积数据
    std::unique_ptr<std::string> buffer = std::make_unique<std::string>();
    res->onData([res, buffer = std::move(buffer)](std::string_view chunk, bool isFin) mutable {
        if (buffer) {
            // 累积数据块
            buffer->append(chunk);
            if(isFin){
                std::cout << "=== HTTP Request body Information ===" << std::endl;
                std::map<std::string, std::string> params;
//                std::cout << "buffer:" <<*buffer << std::endl;
                params = parseFormData(*buffer);
                for(auto [key,value]:params){
                    std::cout << key <<":" << value << std::endl;
                }
                std::cout << "=== HTTP Request end body Information ===" << std::endl;
            }
        }
    });
    std::cout << "=== HTTP Request Information ===" << std::endl;
 
    // 打印方法
    std::cout << "Method: " << req->getMethod() << std::endl;
 
    // 打印URL
    std::cout << "URL: " << req->getUrl() << std::endl;
 
    // 打印查询字符串
    std::cout << "Query String: " << req->getQuery() << std::endl;
 
 
    std::cout << "=== End of Request Information ===" << std::endl;
}

四.测试效果

基于uWebSockets开源库实现一个web服务

五.uWebSockets开源库链接

https://github.com/uNetworking/uWebSockets基于uWebSockets开源库实现一个web服务https://github.com/uNetworking/uWebSockets

© 版权声明

相关文章

暂无评论

none
暂无评论...