当前位置: 首页 > web >正文

《websocketpp使用指北》

目录

websocket协议

websocketpp库

安装websocketpp

websocketpp的用法

websocketpp服务器

结果


websocket协议

WebSocket是一种在单个TCP连接上进行全双工通信的应用协议,允许服务端和客户端实时双向数据传输。它通过HTTP/HTTPS的初始握手建立连接,之后转为独立的WebSocket协议通信,适用于需要低延迟和高频交互的场景(如在线游戏、实时聊天)。

websocket协议的出现就是为了解决http协议服务端无法主动向客户端推送信息的问题。

websocketpp库

websocket协议支持多种语言使用,而websocketpp就是C++语言使用的一套与websocket相关的一套API。

安装websocketpp

1.直接使用linux包管理器安装(Centos要使用yum)

sudo apt-get install libwebsocketpp-dev

2.使用源码安装

git clone https://github.com/zaphoyd/websocketpp.git
cd websocketpp
mkdir build && cd build
cmake ..
make
sudo make install

安装好之后检查是否安装成功,查看该目录是否存在,如果存在说明安装成功了;

指令:ls /usr/include/websocketpp

websocketpp的用法

这里我写了个简单的demo来测试websocketpp的使用。

websocketpp服务器

#pragma once#include <iostream>
#include <websocketpp/connection.hpp>
#include <websocketpp/server.hpp>
#include <websocketpp/close.hpp>
#include <websocketpp/config/asio.hpp>
#include <websocketpp/common/functional.hpp>
#include <functional>
#include <sstream>
#include <unordered_set>
#include <vector>
#include <memory>
#include <atomic>
#include <thread>
#include <unistd.h>typedef websocketpp::server<websocketpp::config::asio> websocket_server; // 服务器别名
typedef websocket_server::message_ptr message_ptr;using msg_callback = std::function<void(websocketpp::connection_hdl, websocket_server::message_ptr)>;class Server
{
public:Server() : _count(0){_server.init_asio();                                         // 初始化服务器_server.set_reuse_addr(true);                                // 设置地址重用_server.set_access_channels(websocketpp::log::alevel::none); // 关闭日志// 设置回调函数_server.set_open_handler(bind(&Server::on_open, this, std::placeholders::_1)); // 回调的时候会自动传递一个connection_hdl参数_server.set_close_handler(bind(&Server::on_close, this, std::placeholders::_1));_server.set_message_handler(bind(&Server::on_message, this, std::placeholders::_1, std::placeholders::_2)); // 两个参数(connection_hdl,message_ptr)}// 设置监听端口void set_listen(int port){_server.listen(port); // 0.0.0.0std::cout << "开始监听端口..." << port << std::endl;}// 开始运行服务器void run(){_server.start_accept();_server.run();}void push_message(){std::thread push_thread([this](){while (true){std::stringstream ss;ss << "服务端第" << _count++ << "次推送信息";if(_connections.size()==0){continue;}// 每过5s推送一次信息for (auto &hdl : _connections){std::string content = get_string();std::string push_message = ss.str() + content;                               // 读取缓冲区数据websocket_server::connection_ptr connection = _server.get_con_from_hdl(hdl); // 获取连接指针// 开始推送信息connection->send(push_message);std::cout << "服务端已经推送新信息: " << content << std::endl;sleep(5);}} });push_thread.detach();}private:// 用于测试服务端主动测试的字符串std::string get_string(){std::string str = "acbakjvbaklbvabildhnakfna";// 使用随机数,随机获取区间,截取int start = rand() % str.size();int end = start + rand() % (str.size() - start);return str.substr(start, end);}// 注册连接回调函数void on_open(websocketpp::connection_hdl hdl){std::cout << "有一个新连接到来..." << std::endl; // 提示信息_connections.insert(hdl);}// 注册关闭回调函数void on_close(websocketpp::connection_hdl hdl){std::cout << "有一个连接关闭..." << std::endl;_connections.erase(hdl);}// 注册处理消息回调函数void on_message(websocketpp::connection_hdl hdl, message_ptr msg){std::string message = msg->get_payload(); // 读取消息std::cout << "客户端消息:" << message << std::endl;// 下面是响应处理逻辑std::string echo_response = "服务端收到消息:";echo_response += message;// 将连接句柄转化为连接指针websocket_server::connection_ptr connection = _server.get_con_from_hdl(hdl);// 发送响应connection->send(echo_response);std::cout << "响应:" << echo_response << std::endl;}// 构建链接句柄哈希struct connection_hdl_hash{std::size_t operator()(const websocketpp::connection_hdl &hdl) const{return reinterpret_cast<std::size_t>(hdl.lock().get());}};struct connection_hdl_equal{bool operator()(const websocketpp::connection_hdl &a, const websocketpp::connection_hdl &b) const{return !a.owner_before(b) && !b.owner_before(a);}};std::unordered_set<websocketpp::connection_hdl,connection_hdl_hash,connection_hdl_equal>_connections;websocket_server _server;std::atomic<size_t> _count;// std::unordered_set<websocketpp::connection_hdl, connection_hdl_hash> _connections;
};class ServerBuilder
{
public:std::shared_ptr<Server> build(){return std::make_shared<Server>();}
};

websocketpp客户端

#include <iostream>
#include <websocketpp/connection.hpp>
#include <websocketpp/client.hpp>
#include <websocketpp/close.hpp>
#include <websocketpp/config/asio.hpp>
#include <websocketpp/common/functional.hpp>
#include <functional>
#include <unordered_set>
#include <vector>using namespace std;using websocket_client = websocketpp::client<websocketpp::config::asio>;// 客户端对象
websocket_client client;// 连接句柄
websocket_client::connection_ptr con_ptr;void on_message(websocketpp::connection_hdl, websocket_client::message_ptr msg)
{cout << "Received message: " << msg->get_payload() << endl;
}void on_open(websocketpp::connection_hdl hdl)
{if (hdl.lock() != nullptr) // lock方法是获取连接句柄的智能指针{std::cout << "连接成功!" << std::endl;con_ptr = client.get_con_from_hdl(hdl);std::thread echo_thread([]() {if (con_ptr != nullptr){while (true){std::cout << "请输入要发送的信息>";std::string message;std::cin >> message;con_ptr->send(message);std::cout << "消息发送成功!" << std::endl;}}});echo_thread.detach();}elsestd::cerr << "连接失败!" << std::endl;
}// 连接关闭时调用的,只要调用了就是连接关闭了
void on_close(websocketpp::connection_hdl hdl)
{if (hdl.lock() != nullptr){std::cout << "连接关闭!" << std::endl;}
}int main()
{client.init_asio();                                         // 初始化client.set_access_channels(websocketpp::log::alevel::none); // 关闭日志client.set_open_handler(&on_open);client.set_message_handler(&on_message);client.set_close_handler(&on_close);websocketpp::lib::error_code ec;auto con = client.get_connection("ws://0.0.0.0:8005", ec);if (ec){std::cout << "连接端口8005失败: " << ec.message() << std::endl;return 1;}client.connect(con);// 不再在 main 中创建输入线程,输入线程在 on_open 回调中启动// 运行客户端client.run();return 0;
}

makefile文件


all:server clientserver:server.cc g++ -o server server.cc -std=c++11 -lboost_system -lssl -lcrypto
client:client.ccg++ -o $@ $^ -std=c++11 -lboost_system -lssl -lcrypto.PHONY:clean
clean:rm -rf server client

结果

http://www.xdnf.cn/news/18994.html

相关文章:

  • ModuleNotFoundError: No module named ‘dbgpt_app‘
  • Python音频分析与线性回归:探索声音中的数学之美
  • 学习游戏制作记录(存档点和丢失货币的保存以及敌人的货币掉落)8.27
  • 计算机网络——DNS,ARP,RARP,DHCP,ICMP
  • Marin说PCB之包地间距对GMSL2信号阻抗的影响分析--01
  • 【图像算法 - 25】基于深度学习 YOLOv11 与 OpenCV 实现人员跌倒识别系统(人体姿态估计版本)
  • 学习 Android (十七) 学习 OpenCV (二)
  • string::erase
  • Prometheus+Grafana监控安装及配置
  • Python 并行计算进阶:ProcessPoolExecutor 处理 CPU 密集型任务
  • 从“找不到”到“秒上手”:金仓文档系统重构记
  • 《电商库存系统超卖事故的技术复盘与数据防护体系重构》
  • 推荐系统王树森(四)特征交叉+行为序列
  • java基础(十六)操作系统(上)
  • 基于单片机光照强度检测(光敏电阻)系统Proteus仿真(含全部资料)
  • 【Qt开发】常用控件(七)-> styleSheet
  • 深度学习(鱼书)day12--卷积神经网络(后四节)
  • Java项目-苍穹外卖_Day3-Day4
  • 深度解析Structured Outputs:基于JSON Schema的结构化输出实践与最佳方案
  • 8月26日
  • 开发避坑指南(37):Vue3 标签页实现攻略
  • iPhone 17 Pro 全新配色确定,首款折叠屏 iPhone 将配备 Touch ID 及四颗镜头
  • 二、JVM 入门 —— (四)堆以及 GC
  • MATLAB中函数的详细使用
  • Slice-100K:推动AI驱动的CAD与3D打印创新的多模态数据集
  • 『专利好药用力心脑血管健康』——爱上古中医(28)(健康生活是coder抒写优质代码的前提条件——《黄帝内经》伴读学习纪要)
  • Hadoop MapReduce 任务/输入数据 分片 InputSplit 解析
  • VS中创建Linux项目
  • VGVLP思路探索和讨论
  • STL库——vector(类函数学习)