《C++开源库介绍与使用》提供详细内容,逐一为每个开源库撰写完整的文章,包括功能介绍、使用方法、实例代码、经典案例分析、问题排查、经验总结、资料扩展和中文解释。(libwebsockets 和 SQLite)的完整文章,延续前文(jsoncpp、RapidJson、TinyXML、libcurl、zip.cpp/unzip.cpp、libqr、libpng、stb_image)的结构和深度。结合您之前的VC++背景(如zlib、时间函数、IM软件),我将确保代码可集成到现有项目,并提供跨库协作案例。

我将按顺序逐批交付,您可随时指定优先级(如OpenCV、FFmpeg)或定制场景(如视频通话)。本响应包含两个库的详细内容、后续计划和综合案例。如果需要调整,请告知!


一、libwebsockets:WebSocket通信库

功能介绍

libwebsockets 是一个轻量级的 C 库,用于实现 WebSocket 协议通信,支持客户端和服务器端,广泛应用于实时应用。核心功能:

  • WebSocket 通信:支持双向、实时、低延迟的数据传输。

  • HTTP 支持:内置 HTTP 服务器,可与 WebSocket 集成。

  • 协议扩展:支持自定义子协议、扩展(如压缩)。

  • 跨平台:支持 Windows、Linux、嵌入式系统。

  • 应用场景:实时聊天、在线游戏、IM 软件消息推送。

libwebsockets 适合需要高效 WebSocket 通信的场景,尤其在 IM 软件中用于实时消息。

使用方法

  1. 安装:

    • vcpkg(推荐):

      bash

      vcpkg install libwebsockets:x64-windows
      vcpkg integrate install
    • 手动下载:从 https://libwebsockets.org/ 或 GitHub(https://github.com/warmcat/libwebsockets)。

    • 编译:

      bash

      git clone https://github.com/warmcat/libwebsockets.git
      cd libwebsockets
      mkdir build && cd build
      cmake .. -G "Visual Studio 16 2019" -DLWS_WITH_SSL=ON
      msbuild libwebsockets.sln
    • 依赖:OpenSSL(SSL 支持)、zlib(可选)。

  2. 配置项目:

    • 包含头文件:#include <libwebsockets.h>。

    • 链接库:websockets.lib(Windows)。

    • 确保 OpenSSL 的 libssl.lib 和 libcrypto.lib 已链接(若启用 SSL)。

  3. 调用接口:

    • 初始化:lws_create_context 创建上下文。

    • 协议:定义 lws_protocols 处理回调。

    • 连接:lws_client_connect(客户端)或 lws_service(服务器)。

    • 清理:lws_context_destroy 释放资源。

实例代码

以下代码展示一个简单的 WebSocket 客户端,连接服务器并发送/接收消息,包含日志记录(参考第7篇时间函数)。

cpp

#include <windows.h>
#include <libwebsockets.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>

#pragma comment(lib, "websockets.lib")
#pragma comment(lib, "libssl.lib")
#pragma comment(lib, "libcrypto.lib")

// 日志记录
void LogMessage(const std::wstring& message) {
    std::wofstream log("ws_log.txt", std::ios::app);
    log << L"[" << std::time(nullptr) << L"] " << message << std::endl;
}

// WebSocket 回调
static int callback_ws(struct lws* wsi, enum lws_callback_reasons reason, void* user, void* in, size_t len) {
    switch (reason) {
    case LWS_CALLBACK_CLIENT_ESTABLISHED:
        LogMessage(L"WebSocket 连接成功");
        lws_callback_on_writable(wsi); // 请求可写
        break;
    case LWS_CALLBACK_CLIENT_WRITEABLE:
    {
        std::string msg = "Hello, Server!";
        std::vector<unsigned char> buf(LWS_PRE + msg.size());
        memcpy(buf.data() + LWS_PRE, msg.c_str(), msg.size());
        lws_write(wsi, buf.data() + LWS_PRE, msg.size(), LWS_WRITE_TEXT);
        LogMessage(L"发送消息: " + std::wstring(msg.begin(), msg.end()));
        break;
    }
    case LWS_CALLBACK_CLIENT_RECEIVE:
        LogMessage(L"接收消息: " + std::wstring((char*)in, (char*)in + len));
        break;
    case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
        LogMessage(L"连接错误: " + (in ? std::wstring((char*)in, (char*)in + len) : L"未知"));
        return -1;
    case LWS_CALLBACK_CLOSED:
        LogMessage(L"WebSocket 连接关闭");
        return -1;
    default:
        break;
    }
    return 0;
}

// 协议定义
static struct lws_protocols protocols[] = {
    { "chat-protocol", callback_ws, 0, 1024, 0, nullptr, 0 },
    { nullptr, nullptr, 0, 0, 0, nullptr, 0 }
};

int wmain() {
    LogMessage(L"程序启动");

    // 初始化 libwebsockets
    struct lws_context_creation_info info = { 0 };
    info.port = CONTEXT_PORT_NO_LISTEN;
    info.protocols = protocols;
    info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
    struct lws_context* context = lws_create_context(&info);
    if (!context) {
        LogMessage(L"创建上下文失败");
        return 1;
    }

    // 连接服务器
    struct lws_client_connect_info ccinfo = { 0 };
    ccinfo.context = context;
    ccinfo.address = "echo.websocket.org";
    ccinfo.port = 443;
    ccinfo.path = "/";
    ccinfo.host = ccinfo.address;
    ccinfo.origin = ccinfo.address;
    ccinfo.protocol = protocols[0].name;
    ccinfo.ssl_connection = LCCSCF_USE_SSL;
    struct lws* wsi = lws_client_connect_via_info(&ccinfo);
    if (!wsi) {
        LogMessage(L"连接服务器失败");
        lws_context_destroy(context);
        return 1;
    }

    // 事件循环
    while (lws_service(context, 1000) >= 0) {
        // 可添加退出条件
    }

    lws_context_destroy(context);
    LogMessage(L"程序结束");
    std::wcout << L"按 Enter 退出..." << std::endl;
    std::wcin.get();
    return 0;
}

经典案例分析

  • 案例:IM 软件实时聊天

    • 场景:IM 客户端(参考第9篇剪切板、第11篇分层窗口)需通过 WebSocket 实现实时消息推送。

    • 实现:

      • 客户端连接:

        cpp

        ccinfo.address = "chat.server.com";
        ccinfo.port = 443;
        ccinfo.path = "/chat";
        lws_client_connect_via_info(&ccinfo);
      • 发送消息:

        cpp

        lws_write(wsi, (unsigned char*)msg.c_str() + LWS_PRE, msg.size(), LWS_WRITE_TEXT);
    • 优点:WebSocket 低延迟,适合实时通信。

    • 挑战:SSL 配置复杂,需处理断线重连。

问题排查与经验总结

  • 问题 1:连接失败

    • 原因:服务器地址错误或 SSL 不可用。

    • 解决:检查 LWS_CALLBACK_CLIENT_CONNECTION_ERROR 的 in 参数,启用 LWS_LOGGING:

      cpp

      lws_set_log_level(LLL_ERR | LLL_WARN | LLL_NOTICE, nullptr);
  • 问题 2:消息丢失

    • 原因:未正确请求 LWS_CALLBACK_CLIENT_WRITEABLE。

    • 解决:发送后调用 lws_callback_on_writable。

  • 经验:

    • 使用 LWS_PRE 预留缓冲区,避免数据覆盖。

    • 实现心跳机制,保持长连接。

    • 调试时启用详细日志,分析回调。

资料扩展

  • 官网:https://libwebsockets.org/

  • GitHub:https://github.com/warmcat/libwebsockets

  • 文档:https://libwebsockets.org/lws-api-doc-master/html/

  • 社区:StackOverflow 搜索“libwebsockets example”。

中文说明

libwebsockets 是一个 WebSocket 通信库,适合 IM 软件实现实时聊天。示例代码展示了客户端连接和消息收发,结合日志记录(参考第7篇时间函数)便于调试。注意 SSL 配置和缓冲区管理,可与 jsoncpp(第1篇)解析消息,或与 libcurl(第4篇)处理 HTTP 登录。


二、SQLite:轻量级数据库

功能介绍

SQLite 是一个轻量级、嵌入式关系型数据库,采用 C 语言实现,无需独立服务器,适合本地数据存储。核心功能:

  • SQL 支持:标准 SQL 查询,表、索引、事务等。

  • 文件存储:数据存储在单个文件中,易于备份。

  • 零配置:无需安装或配置,嵌入应用即可使用。

  • 跨平台:支持 Windows、Linux、嵌入式系统。

  • 应用场景:本地缓存、IM 软件聊天记录、配置文件。

SQLite 是小型应用的理想数据库,适合 IM 软件存储用户数据或消息。

使用方法

  1. 安装:

    • vcpkg(推荐):

      bash

      vcpkg install sqlite3:x64-windows
      vcpkg integrate install
    • 手动下载:从 https://www.sqlite.org/download.html 获取源码或预编译库。

    • 编译:

      bash

      git clone https://github.com/sqlite/sqlite.git
      cd sqlite
      nmake /f Makefile.msc
  2. 配置项目:

    • 包含头文件:#include <sqlite3.h>。

    • 链接库:sqlite3.lib。

    • 无外部依赖。

  3. 调用接口:

    • 打开数据库:sqlite3_open。

    • 执行 SQL:sqlite3_exec(简单查询)或 sqlite3_prepare_v2(参数化)。

    • 关闭:sqlite3_close。

实例代码

以下代码展示如何创建表、插入数据和查询,包含日志记录和中文支持。

cpp

#include <windows.h>
#include <sqlite3.h>
#include <iostream>
#include <fstream>
#include <sstream>

#pragma comment(lib, "sqlite3.lib")

// 日志记录
void LogMessage(const std::wstring& message) {
    std::wofstream log("sqlite_log.txt", std::ios::app);
    log << L"[" << std::time(nullptr) << L"] " << message << std::endl;
}

// 查询回调
static int callback(void* data, int argc, char** argv, char** colNames) {
    std::wstringstream ss;
    ss << L"查询结果: ";
    for (int i = 0; i < argc; ++i) {
        ss << std::wstring(colNames[i], colNames[i] + strlen(colNames[i])) << L"="
           << (argv[i] ? std::wstring(argv[i], argv[i] + strlen(argv[i])) : L"NULL") << L" ";
    }
    LogMessage(ss.str());
    std::wcout << ss.str() << std::endl;
    return 0;
}

int wmain() {
    LogMessage(L"程序启动");

    // 打开数据库
    sqlite3* db;
    int rc = sqlite3_open("chat.db", &db);
    if (rc != SQLITE_OK) {
        LogMessage(L"打开数据库失败: " + std::wstring(sqlite3_errmsg(db), sqlite3_errmsg(db) + strlen(sqlite3_errmsg(db))));
        sqlite3_close(db);
        return 1;
    }
    LogMessage(L"数据库打开成功");

    // 创建表
    const char* createTable = "CREATE TABLE IF NOT EXISTS messages ("
                              "id INTEGER PRIMARY KEY AUTOINCREMENT,"
                              "user TEXT NOT NULL,"
                              "content TEXT NOT NULL,"
                              "timestamp INTEGER);";
    char* errMsg = nullptr;
    rc = sqlite3_exec(db, createTable, nullptr, nullptr, &errMsg);
    if (rc != SQLITE_OK) {
        LogMessage(L"创建表失败: " + std::wstring(errMsg, errMsg + strlen(errMsg)));
        sqlite3_free(errMsg);
        sqlite3_close(db);
        return 1;
    }
    LogMessage(L"表创建成功");

    // 插入数据
    const char* insertStmt = "INSERT INTO messages (user, content, timestamp) VALUES (?, ?, ?);";
    sqlite3_stmt* stmt;
    rc = sqlite3_prepare_v2(db, insertStmt, -1, &stmt, nullptr);
    if (rc != SQLITE_OK) {
        LogMessage(L"准备插入语句失败: " + std::wstring(sqlite3_errmsg(db), sqlite3_errmsg(db) + strlen(sqlite3_errmsg(db))));
        sqlite3_close(db);
        return 1;
    }
    std::string user = "张伟";
    std::string content = "你好!";
    int64_t timestamp = std::time(nullptr);
    sqlite3_bind_text(stmt, 1, user.c_str(), -1, SQLITE_TRANSIENT);
    sqlite3_bind_text(stmt, 2, content.c_str(), -1, SQLITE_TRANSIENT);
    sqlite3_bind_int64(stmt, 3, timestamp);
    rc = sqlite3_step(stmt);
    if (rc != SQLITE_DONE) {
        LogMessage(L"插入数据失败: " + std::wstring(sqlite3_errmsg(db), sqlite3_errmsg(db) + strlen(sqlite3_errmsg(db))));
    } else {
        LogMessage(L"插入数据成功");
    }
    sqlite3_finalize(stmt);

    // 查询数据
    const char* selectStmt = "SELECT id, user, content, timestamp FROM messages;";
    rc = sqlite3_exec(db, selectStmt, callback, nullptr, &errMsg);
    if (rc != SQLITE_OK) {
        LogMessage(L"查询失败: " + std::wstring(errMsg, errMsg + strlen(errMsg)));
        sqlite3_free(errMsg);
    }

    sqlite3_close(db);
    LogMessage(L"程序结束");
    std::wcout << L"按 Enter 退出..." << std::endl;
    std::wcin.get();
    return 0;
}

经典案例 analysis

  • 案例:IM 软件聊天记录

    • 场景:IM 客户端(参考第9篇剪切板)需存储和查询聊天记录。

    • 实现:

      • 插入消息:

        cpp

        sqlite3_bind_text(stmt, 1, "李明", -1, SQLITE_TRANSIENT);
        sqlite3_bind_text(stmt, 2, "下午好!", -1, SQLITE_TRANSIENT);
        sqlite3_step(stmt);
      • 查询历史:

        cpp

        sqlite3_exec(db, "SELECT * FROM messages WHERE user='李明';", callback, nullptr, nullptr);
    • 优点:SQLite 轻量,适合本地存储,事务支持可靠。

    • 挑战:大数据量需优化索引,中文需 UTF-8。

问题排查与经验总结

  • 问题 1:SQLITE_BUSY

    • 原因:数据库被其他线程锁定。

    • 解决:设置超时:sqlite3_busy_timeout(db, 5000)。

  • 问题 2:中文插入失败

    • 原因:非 UTF-8 编码。

    • 解决:确保字符串为 UTF-8:

      cpp

      sqlite3_bind_text(stmt, 1, user.c_str(), -1, SQLITE_TRANSIENT);
  • 经验:

    • 使用参数化查询(sqlite3_bind_*)防止 SQL 注入。

    • 定期备份 .db 文件。

    • 调试时打印 sqlite3_errmsg。

资料扩展

  • 官网:https://www.sqlite.org/

  • 文档:https://www.sqlite.org/docs.html

  • 教程:https://www.sqlitetutorial.net/

  • 社区:StackOverflow 搜索“SQLite C example”。

中文说明

SQLite 是一个嵌入式数据库,适合 IM 软件存储聊天记录或配置。示例代码展示了表创建、数据插入和查询,结合日志记录(参考第7篇时间函数)便于调试。注意 UTF-8 编码和事务管理,可与 libwebsockets(第9篇)结合存储实时消息,或与 zip.cpp(第5篇)备份数据库。


三、后续库计划

以下是剩余 16 个库的计划,每篇将包含类似结构。您可指定优先级:

  1. FFmpeg:多媒体处理,示例:视频转码。

  2. WebRTC:实时音视频,示例:视频通话。

  3. CEF:嵌入浏览器,示例:Web 页面嵌入。

  4. SDL:多媒体开发,示例:音频播放。

  5. CrashRpt/CrashPad:异常捕获,示例:崩溃日志。

  6. ReactOS:系统参考,示例:API 分析。

  7. boost:网络通信,示例:异步 TCP 服务器。

  8. muduo:网络库,示例:高并发服务器。

  9. libevent:事件驱动,示例:事件循环。

  10. OpenCV:计算机视觉,示例:人脸检测。

  11. Yolo:目标检测,示例:物体识别。

  12. RabbitMQ:消息队列,示例:模块通信。

  13. Redis:键值存储,示例:会话缓存。

  14. ZooKeeper:分布式协调,示例:配置管理。

  15. MongoDB:文档数据库,示例:JSON 存储。

  16. MQTT:物联网通信,示例:设备消息。

  17. GStreamer:流媒体,示例:视频流播放。

  18. Live555:实时流,示例:RTSP 服务器。


四、综合案例:IM 软件实时消息与存储

案例:IM 软件消息同步

  • 功能:

    • 使用 libwebsockets 接收实时消息。

    • 使用 SQLite 存储消息记录。

    • 使用 jsoncpp 解析消息内容。

    • 使用 zip.cpp 备份数据库。

    • 使用 libqr 分享聊天记录链接。

  • 代码 framework:

    cpp

    #include <libwebsockets.h>
    #include <sqlite3.h>
    #include <json/json.h>
    #include <zip.h>
    #include <qrencode.h>
    int main() {
        // WebSocket 接收消息
        struct lws_protocols protocols[] = {
            { "chat", callback_ws, 0, 1024 },
            { nullptr, nullptr, 0, 0 }
        };
        struct lws_context* context = lws_create_context(&(struct lws_context_creation_info){ .protocols = protocols });
        lws_client_connect_via_info(&(struct lws_client_connect_info){
            .context = context, .address = "chat.server.com", .port = 443, .path = "/chat", .protocol = "chat"
        });
    
        // 存储消息
        sqlite3* db;
        sqlite3_open("chat.db", &db);
        sqlite3_exec(db, "INSERT INTO messages (user, content, timestamp) VALUES ('张伟', '你好', strftime('%s','now'));", nullptr, nullptr, nullptr);
    
        // 解析消息
        Json::Value msg;
        Json::parseFromStream(Json::CharReaderBuilder(), std::istringstream("{\"user\":\"李明\",\"text\":\"OK\"}"), &msg, nullptr);
    
        // 备份数据库
        CompressFileToZip("chat.db", "backup.zip");
    
        // 生成二维码
        QRcode* qr = QRcode_encodeString("https://server/backup.zip", 0, QR_ECLEVEL_L, QR_MODE_8, 1);
        // SaveQRCodeAsAscii(qr, "backup_qr.txt");
        QRcode_free(qr);
    
        lws_context_destroy(context);
        sqlite3_close(db);
        return 0;
    }

五、总结与下一步

本响应提供了 libwebsockets 和 SQLite 的完整文章,包括功能介绍、实例代码、案例分析和中文说明。代码可集成到您的 IM 软件(参考第9篇、第11篇),与 jsoncpp(第1篇)、zip.cpp(第5篇)、libqr(第6篇)结合使用。剩余 16 个库将按计划继续,您可以:

  1. 指定优先库:如 FFmpeg、OpenCV 或 WebRTC。

  2. 请求完整交付:分批生成所有库。

  3. 定制场景:提供具体需求(如视频通话、图像处理)。

请确认优先级或具体要求,我将提供下一批文章(建议下次提供 FFmpeg 和 WebRTC)!

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐