websocket C++使用

websocket库安装

使用websocketpp C++库进行集成使用,针对的是C++环境编程

下载websocketpp

git clone https://github.com/zaphoyd/websocketpp.git

如果连不上github,头顶连接可以下载,我上传了一份。需要分是默认的,我决定不了。

websocketpp 编译是不会生成库文件的的,使用以下指令进行安装只是将websocketpp文件拷贝到了/usr/local/include目录下。如果你不想安装,可以将该文件夹拷贝到你的工程目录。

cd websocketpp/
mkdir build
cmake ..
make 
sudo make install

安装websocketpp 依赖

sudo apt-get install libboost-all-dev

websocketpp客户端

websocketpp使用查看example文件夹,里面有各种例程。
这里贴一个修改过的,可以获取接收到的消息

#pragma once
#include "websocketpp/config/asio_no_tls_client.hpp"
#include "websocketpp/client.hpp"
#include "websocketpp/common/thread.hpp"
#include "websocketpp/common/memory.hpp"

#include <cstdlib>
#include <iostream>
#include <map>
#include <string>
#include <sstream>
#include <queue>
//websocket 客户端实现
typedef websocketpp::client<websocketpp::config::asio_client> client;

class connection_metadata {
public:
    typedef websocketpp::lib::shared_ptr<connection_metadata> ptr;

    connection_metadata(int id, websocketpp::connection_hdl hdl, std::string uri)
      : id_(id)
      , hdl_(hdl)
      , status_("Connecting")
      , uri_(uri)
      , server_("N/A")
    {}

    void on_open(client * c, websocketpp::connection_hdl hdl) {
        status_ = "Open";

        client::connection_ptr con = c->get_con_from_hdl(hdl);
        server_ = con->get_response_header("Server");
    }

    void on_fail(client * c, websocketpp::connection_hdl hdl) {
        status_ = "Failed";

        client::connection_ptr con = c->get_con_from_hdl(hdl);
        server_ = con->get_response_header("Server");
        error_reason_ = con->get_ec().message();
    }
    
    void on_close(client * c, websocketpp::connection_hdl hdl) {
        status_ = "Closed";
        client::connection_ptr con = c->get_con_from_hdl(hdl);
        std::stringstream s;
        s << "close code: " << con->get_remote_close_code() << " (" 
          << websocketpp::close::status::get_string(con->get_remote_close_code()) 
          << "), close reason: " << con->get_remote_close_reason();
        error_reason_ = s.str();
    }

    void on_message(websocketpp::connection_hdl, client::message_ptr msg) {
        if (msg->get_opcode() == websocketpp::frame::opcode::text) {
            //messages_.push_back("<< " + msg->get_payload());
            {
                std::unique_lock<std::mutex> lock(message_queue_mutex_);
                message_queue_.push(msg->get_payload());
            }
            message_queue_cv_.notify_one();
        } else {
            //messages_.push_back("<< " + websocketpp::utility::to_hex(msg->get_payload()));
        }
    }

    websocketpp::connection_hdl get_hdl() const {
        return hdl_;
    }
    
    int get_id() const {
        return id_;
    }
    
    std::string get_status() const {
        return status_;
    }

    void record_sent_message(std::string message) {
        messages_.push_back(">> " + message);
    }
    bool get_message(std::string& message) {
        std::unique_lock<std::mutex> lock(message_queue_mutex_);
        if (message_queue_.empty()) {
            return false;
        }
        message = message_queue_.front();
        message_queue_.pop();
        return true;
    }
    //阻塞,收到消息返回
    bool get_message_blocking(std::string& message) {
        std::unique_lock<std::mutex> lock(message_queue_mutex_);
        message_queue_cv_.wait(lock, [this] { return !message_queue_.empty(); });
        message = message_queue_.front();
        message_queue_.pop();
        return true;
    }
    friend std::ostream & operator<< (std::ostream & out, connection_metadata const & data);
private:
    int id_;
    websocketpp::connection_hdl hdl_;
    std::string status_;
    std::string uri_;
    std::string server_;
    std::string error_reason_;
    std::vector<std::string> messages_;
    std::queue<std::string> message_queue_;
    std::mutex message_queue_mutex_;
    std::condition_variable message_queue_cv_;
};

std::ostream & operator<< (std::ostream & out, connection_metadata const & data) {
    out << "> URI: " << data.uri_ << "\n"
        << "> Status: " << data.status_ << "\n"
        << "> Remote Server: " << (data.server_.empty() ? "None Specified" : data.server_) << "\n"
        << "> Error/close reason: " << (data.error_reason_.empty() ? "N/A" : data.error_reason_) << "\n";
    out << "> Messages Processed: (" << data.messages_.size() << ") \n";

    std::vector<std::string>::const_iterator it;
    for (it = data.messages_.begin(); it != data.messages_.end(); ++it) {
        out << *it << "\n";
    }

    return out;
}

class WebsocketClient {
public:
    WebsocketClient () : next_id_(0) {
        wsc_.clear_access_channels(websocketpp::log::alevel::all);
        wsc_.clear_error_channels(websocketpp::log::elevel::all);

        wsc_.init_asio();
        wsc_.start_perpetual();

        thread_ = websocketpp::lib::make_shared<websocketpp::lib::thread>(&client::run, &wsc_);
    }

    ~WebsocketClient() {
        wsc_.stop_perpetual();
        
        for (con_list::const_iterator it = connection_list_.begin(); it != connection_list_.end(); ++it) {
            if (it->second->get_status() != "Open") {
                // Only close open connections
                continue;
            }
            
            std::cout << "> Closing connection " << it->second->get_id() << std::endl;
            
            websocketpp::lib::error_code ec;
            wsc_.close(it->second->get_hdl(), websocketpp::close::status::going_away, "", ec);
            if (ec) {
                std::cout << "> Error closing connection " << it->second->get_id() << ": "  
                          << ec.message() << std::endl;
            }
        }
        
        thread_->join();
    }

    int connect(std::string const & uri) {
        websocketpp::lib::error_code ec;

        client::connection_ptr con = wsc_.get_connection(uri, ec);

        if (ec) {
            std::cout << "> Connect initialization error: " << ec.message() << std::endl;
            return -1;
        }

        int new_id = next_id_++;
        connection_metadata::ptr metadata_ptr = websocketpp::lib::make_shared<connection_metadata>(new_id, con->get_handle(), uri);
        connection_list_[new_id] = metadata_ptr;

        con->set_open_handler(websocketpp::lib::bind(
            &connection_metadata::on_open,
            metadata_ptr,
            &wsc_,
            websocketpp::lib::placeholders::_1
        ));
        con->set_fail_handler(websocketpp::lib::bind(
            &connection_metadata::on_fail,
            metadata_ptr,
            &wsc_,
            websocketpp::lib::placeholders::_1
        ));
        con->set_close_handler(websocketpp::lib::bind(
            &connection_metadata::on_close,
            metadata_ptr,
            &wsc_,
            websocketpp::lib::placeholders::_1
        ));
        con->set_message_handler(websocketpp::lib::bind(
            &connection_metadata::on_message,
            metadata_ptr,
            websocketpp::lib::placeholders::_1,
            websocketpp::lib::placeholders::_2
        ));

        wsc_.connect(con);

        return new_id;
    }

    void close(int id, websocketpp::close::status::value code, std::string reason) {
        websocketpp::lib::error_code ec;
        
        con_list::iterator metadata_it = connection_list_.find(id);
        if (metadata_it == connection_list_.end()) {
            std::cout << "> No connection found with id " << id << std::endl;
            return;
        }
        
        wsc_.close(metadata_it->second->get_hdl(), code, reason, ec);
        if (ec) {
            std::cout << "> Error initiating close: " << ec.message() << std::endl;
        }
    }

    void send(int id, std::string message) {
        websocketpp::lib::error_code ec;
        
        con_list::iterator metadata_it = connection_list_.find(id);
        if (metadata_it == connection_list_.end()) {
            std::cout << "> No connection found with id " << id << std::endl;
            return;
        }
        
        wsc_.send(metadata_it->second->get_hdl(), message, websocketpp::frame::opcode::text, ec);
        if (ec) {
            std::cout << "> Error sending message: " << ec.message() << std::endl;
            return;
        }
        
        //metadata_it->second->record_sent_message(message);
    }
    std::string get_status(int id){
        con_list::iterator metadata_it = connection_list_.find(id);
        if (metadata_it == connection_list_.end()) {
            std::cout << "> No connection found with id " << id << std::endl;
            return "unconnect";
        }
        return metadata_it->second->get_status();
    }
    bool get_message(int id, std::string& message) {
        con_list::iterator metadata_it = connection_list_.find(id);
        if (metadata_it == connection_list_.end()) {
            std::cout << "> No connection found with id " << id << std::endl;
            return false;
        }
        return metadata_it->second->get_message(message);
    }

    bool get_message_blocking(int id, std::string& message) {
        con_list::iterator metadata_it = connection_list_.find(id);
        if (metadata_it == connection_list_.end()) {
            std::cout << "> No connection found with id " << id << std::endl;
            return false;
        }
        return metadata_it->second->get_message_blocking(message);
    }

    connection_metadata::ptr get_metadata(int id) const {
        con_list::const_iterator metadata_it = connection_list_.find(id);
        if (metadata_it == connection_list_.end()) {
            return connection_metadata::ptr();
        } else {
            return metadata_it->second;
        }
    }
private:
    typedef std::map<int,connection_metadata::ptr> con_list;

    client wsc_;
    websocketpp::lib::shared_ptr<websocketpp::lib::thread> thread_;

    con_list connection_list_;
    int next_id_;
};

集成使用

int main() {
	WebsocketClient wsc;
	std::string uri = "ws://localhost:9002";
	int id = wsc.connect(uri);
	if (id != -1) {
	    std::cout << "> Created connection with id " << id << std::endl;
	}
	std::string message;
	while(1){
		if (wsc.get_message(id, message)) {
		   std::cout << "Received : " << message << std::endl;
		}
		std::this_thread::sleep_for(std::chrono::milliseconds(500));
		wsc.send(id, "message");
	}
	wsc.close(id,"out");
return 0;
}
### C++WebSocket 通信的实现 #### 使用 Boost 构建 WebSocket 客户端和服务器 为了在 C++ 中实现 WebSocket 通信,Boost.Asio 是一个广泛使用,提供了强大的网络编程功能。通过安装并配置 Boost 来建立 WebSocket 连接[^2]。 安装过程涉及下载指定版本的 Boost 源码包,并编译安装: ```bash wget https://boostorg.jfrog.io/artifactory/main/release/1.73.0/source/boost_1_73_0.tar.bz2 --no-check-certificate tar xvf boost_1_73_0.tar.bz2 cd boost_1_73_0 ./bootstrap.sh --prefix=/usr ./b2 sudo ./b2 install cat /usr/include/boost/version.hpp | grep "BOOST_LIB_VERSION" ``` 完成上述操作后,即可利用 `boost::beast` 实现 WebSocket 的客户端和服务端应用开发。 下面是一个简单的 WebSocket 服务端实例代码片段: ```cpp #include <boost/beast/core.hpp> #include <boost/beast/websocket.hpp> #include <boost/asio/ip/tcp.hpp> namespace beast = boost::beast; namespace http = beast::http; namespace websocket = beast::websocket; using tcp = boost::asio::ip::tcp; int main() { try { boost::asio::io_context ioc{1}; tcp::acceptor acceptor{ioc, {tcp::v4(), 9876}}; for (;;) { beast::flat_buffer buffer; websocket::stream<tcp::socket> ws{ioc}; acceptor.accept(ws.next_layer()); ws.handshake("localhost", "/"); while (true) { beast::multi_buffer recv_buf; ws.read(recv_buf); std::string message = boost::beast::buffers_to_string(recv_buf.data()); // 处理收到的消息 if(message == "exit") break; // 发送响应消息给客户端 ws.write(boost::asio::buffer(std::string("Echo: ") + message)); } } } catch(const std::exception& e){ std::cerr << "Error: " << e.what() << "\n"; } return 0; } ``` 这段程序展示了如何设置监听特定端口的服务端,接受来自客户端连接请求,并处理双向数据交换的过程。 对于想要进一步了解具体细节或遇到其他技术难题的情况,建议查阅官方文档获取更详尽的帮助和支持资料[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值