欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++中實(shí)現(xiàn)WebSocket通信的兩種方法:libwebsockets庫(kù)、Boost.Beast?庫(kù)

 更新時(shí)間:2025年01月11日 10:40:23   作者:希望睿智的技術(shù)小屋  
C++中WebSocket庫(kù)主要有以下幾個(gè)?:cpp-websocket?、asio_websocket?、websockets++?、?websocketpp?、?libwebsockets?、?uWebSockets?、Boost.Beast?、Simple-WebSocket-Server?,這篇文章使用libwebsockets庫(kù)、Boost.Beast?庫(kù)來實(shí)現(xiàn)c++中的WebSocket通信

概述

WebSocket協(xié)議是現(xiàn)代Web開發(fā)中不可或缺的一部分,它允許客戶端和服務(wù)器之間建立持久的連接,實(shí)現(xiàn)雙向?qū)崟r(shí)通信。與傳統(tǒng)的HTTP請(qǐng)求不同,WebSocket提供了一種全雙工的通信通道,使得數(shù)據(jù)可以在任意方向上傳輸,而無需等待對(duì)方請(qǐng)求或者應(yīng)答。

WebSocket是在HTML5中引入的一種新協(xié)議,旨在替代輪詢等技術(shù)來實(shí)現(xiàn)客戶端與服務(wù)器間的實(shí)時(shí)交互。它通過HTTP或HTTPS協(xié)議發(fā)起一個(gè)特殊的請(qǐng)求,一旦連接建立成功,就可以繞過HTTP協(xié)議直接進(jìn)行數(shù)據(jù)交換。其主要的工作流程可以參考下圖。

C++網(wǎng)絡(luò)編程之WebSocket通信_(tái)網(wǎng)絡(luò)編程

握手階段:客戶端發(fā)起一個(gè)HTTP請(qǐng)求,這個(gè)請(qǐng)求與普通的GET請(qǐng)求差不多。但它包含了一些額外的頭字段,比如:Upgrade、Connection、Sec-WebSocket-Key等,表明客戶端希望將現(xiàn)有的TCP連接升級(jí)為WebSocket連接。

連接建立:如果服務(wù)器同意升級(jí),則會(huì)返回一個(gè)狀態(tài)碼為101(Switching Protocols)的響應(yīng),并且同樣帶有Upgrade、Connection等頭字段。

數(shù)據(jù)傳輸:一旦握手完成,雙方就可以開始發(fā)送和接收數(shù)據(jù)幀。每個(gè)幀都包含一個(gè)頭部,指示數(shù)據(jù)是否為二進(jìn)制還是文本形式,以及是否為消息的一部分等信息。

C++中WebSocket庫(kù)

  • cpp-websocket‌:這是一個(gè)C++編寫的WebSocket庫(kù),提供了簡(jiǎn)單易用的API,支持WebSocket握手、消息傳輸和關(guān)閉連接等功能。cpp-websocket的代碼量相對(duì)較小,易于集成到項(xiàng)目中‌。

  • asio_websocket‌:基于Boost.Asio庫(kù)的一個(gè)C++ WebSocket庫(kù)。Boost.Asio是一個(gè)廣泛使用的C++網(wǎng)絡(luò)編程庫(kù),提供了異步I/O操作、事件驅(qū)動(dòng)編程等功能。asio_websocket繼承了Boost.Asio的高性能和靈活性,同時(shí)提供了WebSocket協(xié)議的實(shí)現(xiàn)‌1。

  • websockets++‌:這是一個(gè)C++11編寫的輕量級(jí)WebSocket庫(kù),支持WebSocket握手、消息傳輸和關(guān)閉連接等功能。websockets++提供了簡(jiǎn)潔的API和豐富的文檔,方便開發(fā)者學(xué)習(xí)和使用‌。

  • websocketpp‌:這是一個(gè)功能豐富的C++ WebSocket庫(kù),支持多種WebSocket協(xié)議版本,適用于復(fù)雜的WebSocket通信需求。websocketpp是跨平臺(tái)的開源庫(kù),支持事件驅(qū)動(dòng)接口和靈活的依賴管理‌。

  • libwebsockets‌:這是一個(gè)跨平臺(tái)的C語言庫(kù),支持C++綁定,提供了靈活的WebSocket通信解決方案。libwebsockets適合對(duì)性能有高要求的場(chǎng)景‌。

  • uWebSockets‌:這是一個(gè)簡(jiǎn)單、高效且輕量級(jí)的WebSocket和HTTP實(shí)現(xiàn),底層依賴于libuv庫(kù)。uWebSockets非常適合需要處理大量并發(fā)連接的場(chǎng)景,盡管它在某些平臺(tái)或環(huán)境中的穩(wěn)定性和成熟度可能不如其他庫(kù)‌。

  • Boost.Beast‌:這是一個(gè)基于Boost庫(kù)的WebSocket庫(kù),提供了高性能和易用的API來實(shí)現(xiàn)WebSocket通信。Boost.Beast適用于需要高性能和易用性的場(chǎng)景‌。

  • Simple-WebSocket-Server‌:這是一個(gè)輕量級(jí)的WebSocket庫(kù),適用于簡(jiǎn)單的WebSocket通信需求‌。

libwebsockets庫(kù)

libwebsockets是一個(gè)開源的C語言庫(kù),用于實(shí)現(xiàn)WebSocket和HTTP服務(wù)器及客戶端。它非常靈活,支持多種協(xié)議,適合用于開發(fā)高性能的應(yīng)用程序和服務(wù)。libwebsockets的主要功能如下:

1、WebSocket服務(wù)器和客戶端:支持WebSocket協(xié)議的完整實(shí)現(xiàn),可以創(chuàng)建WebSocket服務(wù)器和客戶端。

2、HTTP服務(wù)器:支持HTTP/1.x和HTTP/2協(xié)議,可以創(chuàng)建高性能的HTTP服務(wù)器。

3、TLS/SSL支持:支持使用OpenSSL進(jìn)行加密,確保通信的安全性。

4、事件驅(qū)動(dòng)模型:采用非阻塞的I/O模型,適合處理大量并發(fā)連接。

5、數(shù)據(jù)壓縮:支持使用zlib進(jìn)行數(shù)據(jù)壓縮,減少帶寬消耗。

6、自定義協(xié)議:允許用戶定義自己的協(xié)議,而不僅僅限于WebSocket和HTTP。

使用libwebsockets庫(kù)開發(fā)WebSocket客戶端主要有六步,其工作流程可以參考下圖。

C++網(wǎng)絡(luò)編程之WebSocket通信_(tái)WebSocket_02

1、初始化庫(kù)和上下文。首先需要初始化libwebsockets庫(kù),使用lws_create_context函數(shù)創(chuàng)建一個(gè)上下文對(duì)象,該對(duì)象包含了庫(kù)運(yùn)行所需的配置信息。

2、創(chuàng)建連接。使用lws_client_connect函數(shù)創(chuàng)建一個(gè)WebSocket連接到指定的服務(wù)器,服務(wù)器的URL由調(diào)用方給出。

3、注冊(cè)回調(diào)函數(shù)。為了處理連接的不同階段,我們需要注冊(cè)回調(diào)函數(shù)。這些回調(diào)函數(shù)會(huì)在特定的事件發(fā)生時(shí)被調(diào)用,比如:連接建立、連接斷開、數(shù)據(jù)接收等。一般在lws_context_creation_info結(jié)構(gòu)體的callbacks字段中,可以指定回調(diào)函數(shù)。

4、發(fā)送和接收數(shù)據(jù)。一旦連接建立,我們便可以開始發(fā)送和接收數(shù)據(jù)。發(fā)送數(shù)據(jù)通常在LWS_CALLBACK_CLIENT_WRITEABLE回調(diào)中進(jìn)行,使用lws_send或lws_write函數(shù),而接收數(shù)據(jù)則在LWS_CALLBACK_CLIENT_RECEIVE回調(diào)中進(jìn)行。

5、處理事件循環(huán)。libwebsockets庫(kù)使用事件循環(huán)來處理網(wǎng)絡(luò)I/O操作,我們需要在一個(gè)無限循環(huán)中調(diào)用lws_service函數(shù)來處理事件。

6、清理資源。當(dāng)不再需要連接時(shí),應(yīng)該釋放所有由libwebsockets分配的資源,通常通過調(diào)用lws_context_destroy函數(shù)來銷毀上下文。

根據(jù)上面的工作流程,我們不難寫出WebSocket客戶端的示例代碼,具體如下。

#include <libwebsockets.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define WEB_SOCKET_MSG                  "Hello From Hope Wisdom"

static lws_context *s_pContext = nullptr;

// WebSocket客戶端回調(diào)函數(shù)
static int OnCallbackWebSocket(struct lws *wsi, enum lws_callback_reasons reason, 
    void *user, void *in, size_t len)
{
    switch(reason)
    {
    case LWS_CALLBACK_CLIENT_ESTABLISHED:
        // 連接已建立
        printf("Connected!\n");
        break;
    case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
        // 連接錯(cuò)誤
        printf("Connection error: %s\n", (char *)in);
        break;
    case LWS_CALLBACK_CLIENT_CLOSED:
        // 連接關(guān)閉
        printf("Disconnected.\n");
        break;
    case LWS_CALLBACK_CLIENT_RECEIVE:
        // 接收數(shù)據(jù)
        printf("Received: %.*s\n", (int)len, (const char *)in);
        break;
    case LWS_CALLBACK_CLIENT_WRITEABLE:
        // 當(dāng)連接可寫時(shí),可以發(fā)送數(shù)據(jù)
        if (lws_send(wsi, WEB_SOCKET_MSG, strlen(WEB_SOCKET_MSG), LWS_SEND_TEXT) < 0)
        {
            printf("Send failed!\n");
        }
        break;
    default:
        break;
    }

    return 0;
}

static int init_lws()
{
    struct lws_context_creation_info info;
    lws_zeroize(&info, sizeof(info));
    info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT | LWS_SERVER_OPTION_VALIDATE_UTF8;
    // 設(shè)置回調(diào)函數(shù)
    info.callbacks = &OnCallbackWebSocket;
    // 設(shè)置端口(客戶端不需要監(jiān)聽端口)
    info.port = LWS_NO_LISTEN;
    info.name = "Client";

    // 創(chuàng)建上下文
    s_pContext = lws_create_context(&info);
    if (!s_pContext)
    {
        printf("Failed to create context\n");
        return -1;
    }

    return 0;
}

static int connect_to_server(const char *uri)
{
    struct lws *wsi = nullptr;
    wsi = lws_client_connect(s_pContext, uri, nullptr, LWS_CLIENT_CONNECT);
    if (!wsi)
    {
        printf("Failed to connect to %s\n", uri);
        return -1;
    }

    return 0;
}

int main(int argc, char **argv)
{
    if (argc < 2)
    {
        printf("Usage: %s <websocket-uri>\n", argv[0]);
        return -1;
    }

    // 初始化libwebsockets庫(kù)
    if (init_lws() < 0)
    {
        return -1;
    }

    // 連接到WebSocket服務(wù)器
    if (connect_to_server(argv[1]) < 0)
    {
        return -1;
    }

    // 主事件循環(huán)
    while (lws_service(s_pContext, 0))
    {
        // 自動(dòng)處理連接的讀寫
    }

    // 釋放資源
    lws_context_destroy(s_pContext);
    return 0;
}

Boost.Beast擴(kuò)展

Boost.Beast,可簡(jiǎn)稱為Beast,是Boost庫(kù)中的一個(gè)子項(xiàng)目。它是一個(gè)現(xiàn)代C++網(wǎng)絡(luò)庫(kù),主要用于構(gòu)建高性能的網(wǎng)絡(luò)應(yīng)用程序和服務(wù)。Beast是專門為C++11及更高版本設(shè)計(jì)的,它利用了現(xiàn)代C++語言的特性,比如:移動(dòng)語義、智能指針等,以提高軟件整體性能。

Beast的主要組件包括:基礎(chǔ)的網(wǎng)絡(luò)抽象(比如:Stream、Buffer)、HTTP(包括:HTTP/1.x、HTTP/2)、WebSockets等。其主要特點(diǎn)如下。

1、基于Boost.Asio。Beast是基于Boost.Asio的高級(jí)網(wǎng)絡(luò)庫(kù),因此它可以無縫集成到任何使用Boost.Asio的項(xiàng)目中。Beast提供了異步IO模型,允許非阻塞的操作,這對(duì)于構(gòu)建高并發(fā)的網(wǎng)絡(luò)服務(wù)非常重要。

2、高性能。設(shè)計(jì)用于高性能的應(yīng)用場(chǎng)景,支持高效的內(nèi)存管理,避免不必要的內(nèi)存拷貝。提供了零拷貝機(jī)制,即在傳輸數(shù)據(jù)時(shí)不進(jìn)行內(nèi)存復(fù)制,而是直接使用原始數(shù)據(jù)緩沖區(qū)。

3、易于使用。提供了簡(jiǎn)潔的API,使得編寫網(wǎng)絡(luò)應(yīng)用程序變得更加直觀和容易。支持錯(cuò)誤處理機(jī)制,使得捕獲和處理網(wǎng)絡(luò)錯(cuò)誤變得更加容易。

4、協(xié)議支持。支持多種網(wǎng)絡(luò)協(xié)議,包括:HTTP/1.x、HTTP/2、WebSockets等。另外,還提供了HTTP和WebSocket的客戶端和服務(wù)器實(shí)現(xiàn)。

5、跨平臺(tái)。Beast可以在多個(gè)操作系統(tǒng)上運(yùn)行,包括:Windows、Linux、MacOS等。它具有良好的跨平臺(tái)兼容性,使得開發(fā)者可以編寫一次代碼并在不同平臺(tái)上運(yùn)行。

使用Beast庫(kù)編寫WebSocket客戶端比較簡(jiǎn)單,示例代碼如下。

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

using namespace std;

namespace beast = boost::beast;
namespace http = beast::http;
namespace net = boost::asio;
using tcp = net::ip::tcp;

int main()
{
    try {
        // 創(chuàng)建I/O上下文和解析器
        net::io_context ioc;
        tcp::resolver resolver(ioc);

        // 解析服務(wù)器地址和端口
        auto endpoints = resolver.resolve("echo.websocket.org", "80");

        // 創(chuàng)建并連接socket
        tcp::socket socket(ioc);
        beast::get_lowest_layer(socket).connect(endpoints);

        // 設(shè)置HTTP請(qǐng)求
        http::request<http::string_body> req{http::verb::get, "/", 11};
        req.set(http::field::host, "echo.websocket.org");
        req.set(http::field::upgrade, "websocket");
        req.set(http::field::connection, "Upgrade");
        // 隨機(jī)的Base64編碼的WebSocket密鑰
        req.set(http::field::sec_websocket_key, "dGhlIHNhbXBsZSBub25Nl29rZXk=");
        req.set(http::field::sec_websocket_version, "13");

        // 使用websocket::stream進(jìn)行握手  
        websocket::stream<tcp::socket> ws{ioc};
        ws.assign(std::move(socket));

        // 發(fā)送HTTP升級(jí)請(qǐng)求并接收響應(yīng)來完成握手  
        http::response<http::string_body> res;  
        ws.handshake(req, res);

        // 發(fā)送消息到服務(wù)器
        beast::error_code ec;
        ws.write(net::buffer("Hello, Hope Wisdom"), ec);

        // 接收消息
        while (true) 
        {
            beast::flat_buffer receive_buffer;
            websocket::opcode op;
            ws.read(op, receive_buffer);

            ws.consume(receive_buffer.data().size());
            if (op == websocket::opcode::close)
            {
                break;
            }

            cout << "Received: " << beast::buffers_to_string(receive_buffer.data()) << endl;
        }

        // 關(guān)閉連接
        ws.close(websocket::close_code::normal);
    }
    catch (exception const& e)
    {
        cerr << "Error: " << e.what() << endl;
    }

    return 0;
}

在上面的示例代碼中,我們首先創(chuàng)建了一個(gè)I/O上下文io_context和一個(gè)DNS解析器resolver,解析了服務(wù)器的地址和端口。接著,我們創(chuàng)建了一個(gè)TCP套接字,并使用解析結(jié)果中的端點(diǎn)列表連接到服務(wù)器。隨后,設(shè)置了HTTP請(qǐng)求,以發(fā)起WebSocket的握手請(qǐng)求,其中包括了必要的頭部信息,比如:Upgrade、Connection、Sec-WebSocket-Key、Sec-WebSocket-Version。這些頭部信息用于告知服務(wù)器希望將連接升級(jí)為WebSocket連接,并提供了握手所需的密鑰和版本號(hào)。

為了執(zhí)行WebSocket握手,我們創(chuàng)建了一個(gè)stream<socket>對(duì)象ws,并將之前的TCP套接字socket賦值給它。然后,調(diào)用ws.handshake函數(shù)來發(fā)送HTTP升級(jí)請(qǐng)求,并接收響應(yīng)以完成握手過程。

握手完成后,我們通過ws.write函數(shù)發(fā)送了一條文本消息到服務(wù)器。隨后,進(jìn)入一個(gè)無限循環(huán),不斷接收來自服務(wù)器的消息。每次接收到消息后,都會(huì)檢查是否為關(guān)閉幀。如果是,則退出循環(huán)。否則,打印接收到的消息。

最后,在退出循環(huán)時(shí),我們會(huì)釋放資源,關(guān)閉WebSocket連接和TCP套接字。

總結(jié)

C++中WebSocket庫(kù)主要有以下幾個(gè)‌:cpp-websocket‌、asio_websocket‌、websockets++‌、‌websocketpp‌、‌libwebsockets‌、‌uWebSockets‌、Boost.Beast‌、Simple-WebSocket-Server‌,這篇文章使用libwebsockets庫(kù)、Boost.Beast‌庫(kù)來實(shí)現(xiàn)c++中的WebSocket通信。

到此這篇關(guān)于C++中實(shí)現(xiàn)WebSocket通信的兩種方法:libwebsockets庫(kù)、Boost.Beast‌庫(kù)的文章就介紹到這了,更多相關(guān)C++中WebSocket通信內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • opencv實(shí)現(xiàn)機(jī)器視覺檢測(cè)和計(jì)數(shù)的方法

    opencv實(shí)現(xiàn)機(jī)器視覺檢測(cè)和計(jì)數(shù)的方法

    在機(jī)器視覺中,有時(shí)需要對(duì)產(chǎn)品進(jìn)行檢測(cè)和計(jì)數(shù)。其難點(diǎn)無非是對(duì)于產(chǎn)品的圖像分割。本文就來介紹一下機(jī)器視覺檢測(cè)和計(jì)數(shù)的實(shí)現(xiàn),感興趣的可以參考一下
    2021-05-05
  • C++類常量和類枚舉

    C++類常量和類枚舉

    這篇文章主要介紹了C++類常量和類枚舉,給類當(dāng)中定義一些常量,可以給所有類的對(duì)象使用,比如說我們?cè)陬惍?dāng)中定義一個(gè)數(shù)組,希望可以定義一個(gè)常量,用來初始化數(shù)組的長(zhǎng)度,那么下面我i嗎就來看看過程當(dāng)如何吧
    2022-01-01
  • C語言深入探索之單鏈表與typedef的用法

    C語言深入探索之單鏈表與typedef的用法

    typedef為C語言的關(guān)鍵字,作用是為一種數(shù)據(jù)類型定義一個(gè)新名字,單鏈表是后面要學(xué)的雙鏈表以及循環(huán)鏈表的基礎(chǔ),要想繼續(xù)深入了解數(shù)據(jù)結(jié)構(gòu)以及C語言,我們就要奠定好這塊基石!接下來就和我一起學(xué)習(xí)吧
    2022-05-05
  • 在C++中如何阻止類被繼承詳解

    在C++中如何阻止類被繼承詳解

    這篇文章主要介紹了在C++中如何阻止類被繼承,對(duì)于C++初學(xué)者而言可以通過本文實(shí)例更好的理解類的原理及運(yùn)用,需要的朋友可以參考下
    2021-09-09
  • C++?set的使用示例詳解

    C++?set的使用示例詳解

    序列式容器如vector、list等存儲(chǔ)數(shù)據(jù)的邏輯結(jié)構(gòu)為線性序列,元素的存儲(chǔ)和訪問是按位置順序進(jìn)行的,而關(guān)聯(lián)式容器如set、map等,本文給大家介紹C++?set的使用示例詳解,感興趣的朋友一起看看吧
    2024-10-10
  • 深入講解C++中的構(gòu)造函數(shù)

    深入講解C++中的構(gòu)造函數(shù)

    這篇文章主要介紹了C++中的構(gòu)造函數(shù),是C++入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-09-09
  • C++實(shí)現(xiàn)簡(jiǎn)單的圖書管理系統(tǒng)

    C++實(shí)現(xiàn)簡(jiǎn)單的圖書管理系統(tǒng)

    本文給大家分享的是使用C++實(shí)現(xiàn)簡(jiǎn)單的圖書管理系統(tǒng)的代碼,本系統(tǒng)采用了面向?qū)ο蟮某绦蛟O(shè)計(jì)方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2015-08-08
  • c++實(shí)現(xiàn)獲取當(dāng)前時(shí)間(精確至秒,毫秒和微妙)

    c++實(shí)現(xiàn)獲取當(dāng)前時(shí)間(精確至秒,毫秒和微妙)

    這篇文章主要為大家詳細(xì)介紹了c++實(shí)現(xiàn)獲取當(dāng)前時(shí)間(可以精確至秒,毫秒和微妙)的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以參考一下
    2023-11-11
  • C++11中std::async的使用詳解

    C++11中std::async的使用詳解

    這篇文章主要介紹了C++11中std::async的使用詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02
  • 關(guān)于C++靜態(tài)數(shù)據(jù)成員的實(shí)現(xiàn)講解

    關(guān)于C++靜態(tài)數(shù)據(jù)成員的實(shí)現(xiàn)講解

    今天小編就為大家分享一篇關(guān)于關(guān)于C++靜態(tài)數(shù)據(jù)成員的實(shí)現(xiàn)講解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2018-12-12

最新評(píng)論