如何使用 websocket websocketpp 发送和接收消息?

Posted

技术标签:

【中文标题】如何使用 websocket websocketpp 发送和接收消息?【英文标题】:How to sending and receiving messages with websocket websocketpp? 【发布时间】:2020-05-07 10:59:30 【问题描述】:

我有一个 C++ 小代码,我正在尝试使用 websocketpp 库

我使用的是可用客户端/服务器的示例,但终端仅显示已连接。

https://github.com/zaphoyd/websocketpp

我是 C++ 的初学者,所以我很感激我能提供帮助。因为我在学习websocket的语言和技术。

服务器

#include <iostream>
// WebService
#include <set>
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>
#include <functional>


typedef websocketpp::server<websocketpp::config::asio> server;

class utility_server 
public:
    utility_server() 
        // Set logging settings
        m_endpoint.set_error_channels(websocketpp::log::elevel::all);
        m_endpoint.set_access_channels(websocketpp::log::alevel::all ^ websocketpp::log::alevel::frame_payload);

        // Initialize Asio
        m_endpoint.init_asio();

        // Set the default message handler to the echo handler
        m_endpoint.set_message_handler(std::bind(
            &utility_server::echo_handler, this,
            std::placeholders::_1, std::placeholders::_2
        ));
    

    void echo_handler(websocketpp::connection_hdl hdl, server::message_ptr msg) 
        // write a new message
        m_endpoint.send(hdl, msg->get_payload(), msg->get_opcode());
    

    void run() 
        // Listen on port 9002
        m_endpoint.listen(9002);

        // Queues a connection accept operation
        m_endpoint.start_accept();

        // Start the Asio io_service run loop
        m_endpoint.run();
    
private:
    server m_endpoint;
;

int main()

    utility_server s;
    s.run();
    return 0;

客户

#include <websocketpp/config/asio_no_tls_client.hpp>
#include <websocketpp/client.hpp>

#include <iostream>

typedef websocketpp::client<websocketpp::config::asio_client> client;

using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind;

// pull out the type of messages sent by our config
typedef websocketpp::config::asio_client::message_type::ptr message_ptr;

// This message handler will be invoked once for each incoming message. It
// prints the message and then sends a copy of the message back to the server.
void on_message(client* c, websocketpp::connection_hdl hdl, message_ptr msg) 
    std::cout << "on_message called with hdl: " << hdl.lock().get()
        << " and message: " << msg->get_payload()
        << std::endl;


    websocketpp::lib::error_code ec;

    c->send(hdl, msg->get_payload(), msg->get_opcode(), ec);
    if (ec) 
        std::cout << "Echo failed because: " << ec.message() << std::endl;
    


int main(int argc, char* argv[]) 
    // Create a client endpoint
    client c;

    std::string uri = "ws://localhost:9002";

    if (argc == 2) 
        uri = argv[1];
    

    try 
        // Set logging to be pretty verbose (everything except message payloads)
        c.set_access_channels(websocketpp::log::alevel::all);
        c.clear_access_channels(websocketpp::log::alevel::frame_payload);

        // Initialize ASIO
        c.init_asio();

        // Register our message handler
        c.set_message_handler(bind(&on_message, &c, ::_1, ::_2));

        websocketpp::lib::error_code ec;
        client::connection_ptr con = c.get_connection(uri, ec);
        if (ec) 
            std::cout << "could not create connection because: " << ec.message() << std::endl;
            return 0;
        

        // Note that connect here only requests a connection. No network messages are
        // exchanged until the event loop starts running in the next line.
        c.connect(con);

        // Start the ASIO io_service run loop
        // this will cause a single connection to be made to the server. c.run()
        // will exit when this connection is closed.
        c.run();
    
    catch (websocketpp::exception const& e) 
        std::cout << e.what() << std::endl;
    

【问题讨论】:

【参考方案1】:

您需要使用客户端实例调用 send() 方法;各种重载记录在here。编辑:实际上我可以看到您已经在调用它,但是在错误的位置。因为它在on消息处理程序中,所以它只有在收到消息时才会发送。并且服务器代码本身不发送任何消息,因此客户端中的发送永远不会触发。 websocketpp 示例将 send 放在 open 处理程序中,但除了演示之外,这是一个非常无用的用例。

通常,您希望直接从您的应用程序代码中调用 send。棘手的一点是如何协商这样一个事实,即您必须先调用 run() 才能对客户端执行任何操作,并且 run 是一个阻塞调用(这意味着您不能在之后调用 send )。这个问题的答案是有一个线程专门用于调用 run(),它允许您在主线程(或您想要的任何线程)上调用 send()。

既然您说您是 C++ 新手,我建议您先了解线程:了解如何优雅地启动和停止它们,并了解线程安全。在 C++ 中有几种使用线程的方法,但我建议在这种情况下查看 std::thread。

一旦您了解了如何在 C++ 中使用线程,然后尝试将其构建到您的应用程序中。最终,为您的客户端创建一个处理线程和发送消息等的类将是一个好主意。

一旦你得到一些工作,我建议阅读websocketpp FAQ),特别是“我如何干净地退出基于 Asio 传输的程序”部分。

【讨论】:

以上是关于如何使用 websocket websocketpp 发送和接收消息?的主要内容,如果未能解决你的问题,请参考以下文章

为啥火币服务器收不到 C# WebSocket Ping?

WebSocket 反爬虫

websocket 和 websocket-client,如何同时使用?

如何从 websocket 端点外部发出 websocket 消息?

Golang如何使用websocket

WebSocket原理及如何使用