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

websocketpp库使用:快速搭建一个websocket服务端

目录

1.websocket协议

1.1websocket协议诞生的原因

1.2websocket VS http

1.3websocket协议报头

2.websocketpp搭建简单服务器


1.websocket协议

1.1websocket协议诞生的原因

传统的 HTTP 协议采用的是请求 - 响应的单向通信模式,即客户端必须主动发起请求,服务器才能做出响应。在需要实时更新数据的场景下,如在线聊天、实时股票行情显示等,客户端为了获取最新信息,不得不频繁地向服务器发送请求,这种方式会造成大量不必要的网络流量和服务器负载,同时也无法保证数据的实时性。

1.2websocket VS http

1.3websocket协议报头

websocket协议通常是由http协议切换而来的。

客户端会向服务器发送一个,含有websocket信息的请求。

GET /chat HTTP/1.1
Host: example.com:8080
Upgrade: websocket //表明客户端希望将当前的 HTTP 连接升级为 WebSocket 连接
Connection: Upgrade //告知服务器将http协议切换为websocket
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== 
Sec-WebSocket-Version: 13
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits

Upgrade: websocket 表明客户端希望将当前的 HTTP 连接升级为 WebSocket 连接

Connection: Upgrade 告知服务器需要进行协议升级。

Sec-WebSocket-Key:一个 Base64 编码的随机值,用于防止普通的 HTTP 连接被误当作 WebSocket 连接。服务器会使用这个值进行计算并在响应中返回一个加密的键,以此验证连接的合法性。

Sec-WebSocket-Version:指定客户端支持的 WebSocket 协议版本,目前常用的版本是 13。

服务器收到客户端的升级请求后,如果同意升级,会返回一个状态码为 101 的响应,并包含相应的报头信息。

FIN:表示这是否是消息的最后一帧。

如果为 1,则表示该消息已完整传输;如果为 0,则表示后续还有其他帧。

Opcode:用于指示帧的类型。

常见的操作码包括 0x0(延续帧)、0x1(文本帧)、0x2(二进制帧)、0x8(关闭帧)、0x9(Ping 帧)和 0xA(Pong 帧)。

Mask:表示是否对数据进行掩码处理。

客户端发送的帧必须进行掩码处理,服务器发送的帧不能进行掩码处理。

Payload length:表示负载数据的长度。

如果值在 0 - 125 之间,则直接使用 7 位表示;如果为 126,则接下来的 16 位表示负载长度;如果为 127,则接下来的 64 位表示负载长度

Mask-Key:当mask为1时存在,长度为4字节,

解码规则:DECODED[i]=ENCODED[i]^MASK[i %4]

Payloaddata:报文携带的载荷数据

2.websocketpp搭建简单服务器

#include <iostream>
#include <websocketpp/server.hpp>
#include <websocketpp/config/asio_no_tls.hpp>
#include <string>

//websocketpp::server<websocketpp::config::asio> 指定asio网络库作为websocket的服务器
typedef websocketpp::server<websocketpp::config::asio> ws;
typedef websocketpp::server<websocketpp::config::asio>::message_ptr message_ptr;
typedef websocketpp::server<websocketpp::config::asio>::connection_ptr connection_ptr;

//websocketpp::connection_hdl conn 是一个表示连接的句柄,本身没有什么意义
void httpCallBack(ws *server, websocketpp::connection_hdl conn) 
{
    std::cout <<"get a http request " << std::endl;
    connection_ptr connPtr = server->get_con_from_hdl(conn);// 通过句柄获取一个真正的连接
    std::string response = R"(<html><p>hello word<p></html>)";
    connPtr->set_body(response);
    connPtr->set_status(websocketpp::http::status_code::ok);
}

void openCallBack(ws *server, websocketpp::connection_hdl conn)
{
    std::cout <<"get a new connection " << std::endl;
}

void closeCallBack(ws *server, websocketpp::connection_hdl conn)
{
    std::cout <<"a connection closed" << std::endl;
}

void messageCallBack(ws *server, websocketpp::connection_hdl conn, message_ptr message)
{
    std::cout << "a message come" << std::endl;
    server->send(conn, message->get_payload(),websocketpp::frame::opcode::text);
}

int main()
{
    //1.创建websocket服务实例
    ws server;
    //2.设置日志等级
    server.set_access_channels(websocketpp::log::alevel::none);
    //3.初始化asio
    server.init_asio();
    //4.设置地址重用
    server.set_reuse_addr(true);
    //5.设置回调函数
    //设置http请求的回调函数
    server.set_http_handler(std::bind(&httpCallBack, &server, std::placeholders::_1));
    //设置websocket请求的回调函数
    server.set_open_handler(std::bind(&openCallBack, &server, std::placeholders::_1)); //建立连接成功的回调
    server.set_close_handler(std::bind(&closeCallBack, &server, std::placeholders::_1));//连接关闭的回调
    server.set_message_handler(std::bind(&messageCallBack, &server, std::placeholders::_1, std::placeholders::_2));//消息到来的回调
    //6.设置端口
    server.listen(8080);
    //7.接受连接
    server.start_accept();
    //8.运行服务
    server.run();
    return 0;
}
websocket:websocket.cc
	g++ -o $@ $^ -std=c++11 -lpthread -lboost_system

.PHONY:clean
clean:
	rm -rf websocket

相关文章:

  • 在带有Intel Arc GPU的Windows上安装IPEX-LLM
  • 【C++】C++ 旅馆管理系统(含 源码+报告)【独一无二】
  • [鸿蒙笔记-基础篇_生命周期篇] Harmony OS
  • 【Azure 架构师学习笔记】- Azure Databricks (11) -- UC搭建
  • oracle查看执行计划
  • 操作系统知识速记:实现线程同步的方式
  • 2025年3月一区SCI-真菌生长优化算法Fungal growth optimizer-附Matlab免费代码
  • python 浅拷贝和深拷贝
  • Java并发中的CAS机制:原理、应用与挑战(通俗易懂版)
  • 【含文档+PPT+源码】基于微信小程序的乡村振兴民宿管理系统
  • c# sqlite 批量生成insert语句的函数
  • ubuntu基于docker部署呼叫中心质检【支持情绪,话术对比】
  • 计算机组成原理—— 总线系统(十一)
  • DeepSeek HuggingFace 70B Llama 版本 (DeepSeek-R1-Distill-Llama-70B)
  • 【MediaTek】 T750 openwrt-23.05编 cannot find dependency libexpat for libmesode
  • 对比 LVS 负载均衡群集的 NAT 模式和 DR 模式,比较其各自的优势 , 基于 openEuler 构建 LVS-DR 群集。
  • 【linux】文件与目录命令 - cut
  • 微信小程序地图标记点,安卓手机一次性渲染不出来的问题
  • node.js下载、安装、设置国内镜像源(永久)(Windows11)
  • 【愚公系列】《Python网络爬虫从入门到精通》008-正则表达式基础
  • 网站备案咨询/网络营销的策略有哪些
  • 网站企业建设/长沙seo网站排名优化公司
  • 有哪些做的好的小众网站/怎么卸载windows优化大师
  • python 做网站/推广app拉人头赚钱
  • 网站开发团队 需要哪些角色/小红书关键词搜索量查询
  • 用网站做数据库吗/seo百度站长工具