概述
基于 C++ 标准的 WebSocket 协议实现,适合使用 C++11 或更高版本开发的项目,支持构建 WebSocket 客户端和服务器,功能灵活,设计模块化,非常适合高性能的网络通信场景
主要特点
- 支持 WebSocket 客户端和服务器
- 默认支持同步和异步 I/O;可以与 Boost.Asio 或其他异步 I/O 库集成,适应多种开发需求
- 支持加密的 WebSocket 通信,需要链接 OpenSSL 等库
- 通过 C++11 的特性优化性能(如智能指针、线程等);提供事件回调机制,减少资源占用
- 支持自定义协议、扩展和日志记录;可以根据项目需要启用或禁用功能
原理理解
Websocket本质是TCP协议。客户端先和服务器先通过HTTP请求,然后在这个请求的基础上完成握手过程同时升级协议
报文格式
FIN
:表示该消息是否结束Opcode
:指明帧类型(如文本帧、二进制帧、关闭帧等)Mask
:表示是否使用掩码(客户端消息必须使用掩码)Payload length
:表示数据长度Payload data
:实际的数据
全双工通信
一旦握手完成,客户端和服务器之间的连接是全双工的,允许任意一方主动发送或接收消息,而无需等待请求/响应模型
核心实现理解
网络通信
Websocket++是建立在Boost::Asio的网络通信机制上的,其是支持异步通信以及可以通过TCP连接实现底层的字节流传输
事件驱动模型
WebSocket++
使用事件驱动模型来处理连接的生命周期
on_open
:处理连接建立事件on_message
:处理消息接收事件on_close
:处理连接关闭事件on_fail
:处理连接失败事件
双向通信的实现
- 收到消息时,通过事件处理函数将消息传递给用户定义的回调函数
- 发送消息时,将数据封装为帧并通过 TCP 发送
常用接口
Server类
Server类的主要功能就是快速搭建一个Websocket服务器,其内部封装了Websocket协议的所有服务器端功能,提供了处理连接、接收消息、发送消息等功能
init_asio()
初始化 ASIO 库。WebSocket++ 使用 ASIO 作为底层网络通信库,因此需要调用此函数来初始化 ASIO
server.init_asio();
set_reuse_addr()
启用地址复用,在服务器端快速启动或重启 WebSocket 服务
server.set_reuse_addr(true);
set_open_handler()
设置 WebSocket 连接打开时的回调函数。当一个客户端连接到服务器时,调用该回调
server.set_open_handler([](websocketpp::connection_hdl hdl) {std::cout << "Client connected!" << std::endl;
});
set_close_handler()
设置 WebSocket 连接关闭时的回调函数。连接关闭时将调用该回调
server.set_close_handler([](websocketpp::connection_hdl hdl) {std::cout << "Client disconnected!" << std::endl;
});
set_message_handler()
设置接收到消息时的回调函数。客户端发送消息时,会触发该回调函数
server.set_message_handler([](websocketpp::connection_hdl hdl, server::message_ptr msg) {std::cout << "Received message: " << msg->get_payload() << std::endl;
});
listen()
启动服务器并监听指定的端口
server.listen(9002); // 在端口 9002 上监听
run()
启动事件循环,等待和处理客户端连接和消息
server.run();
Client类
用于 WebSocket 客户端。它也提供了类似于服务器端的功能,包括连接管理、消息处理等
init_asio()
client.init_asio();
set_open_handler()
设置连接建立时的回调函数
client.set_open_handler([](websocketpp::connection_hdl hdl) {std::cout << "Connection established!" << std::endl;
});
set_close_handler()
设置连接关闭时的回调函数
client.set_close_handler([](websocketpp::connection_hdl hdl) {std::cout << "Connection closed!" << std::endl;
});
set_message_handler()
设置接收到消息时的回调函数
client.set_message_handler([](websocketpp::connection_hdl hdl, client::message_ptr msg) {std::cout << "Received message: " << msg->get_payload() << std::endl;
});
connect()
建立 WebSocket 连接
client.connect(endpoint);
run()
启动事件循环,等待并处理消息
client.run();
websocketpp::connection_hdl
websocketpp::connection_hdl是Websocket++中的一个句柄,其表示一个Websocket连接的唯一标识符;其可以传递给服务器和客户端的处理函数,用于标识连接,从而帮助我们执行特定连接的操作
message类
封装了 WebSocket 消息的数据。它包含了消息的有效负载和其他相关信息
get_payload()
:获取消息的有效负载部分,即客户端或服务器接收到的消息内容
std::string payload = msg->get_payload();
set_payload()
:设置消息的有效负载部分
msg->set_payload("Hello, WebSocket!");
使用
服务器搭建
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>//1. 定义Server类型
typedef websocketpp::server<websocketpp::config::asio> server_t;void onOpen(websocketpp::connection_hdl hdl) {std::cout << "websocket长连接建立成功!\n";
}
void onClose(websocketpp::connection_hdl hdl) {std::cout << "websocket长连接断开!\n";
}
void onMessage(server_t *server, websocketpp::connection_hdl hdl, server_t::message_ptr msg)
{//获取有效载荷信息然后进行业务处理std::string body = msg->get_payload();std::cout<<"收到消息:"<<body<<std::endl;//获取通信连接auto conn = server->get_con_from_hdl(hdl);//发送数据conn->send(body + "-Hello!", websocketpp::frame::opcode::value::text);
}int main()
{//2. 实例化服务器对象server_t server;//3. 初始化日志输出server.set_access_channels(websocketpp::log::alevel::none);//4. 初始化asio框架server.init_asio();// 5. 设置消息处理、连接握手成功、连接关闭回调函数server.set_open_handler(onOpen);server.set_close_handler(onClose);auto msg_hadler = std::bind(onMessage, &server, std::placeholders::_1, std::placeholders::_2);server.set_message_handler(msg_hadler);// 6. 设置监听端口server.set_reuse_addr(true);// 7. 开始监听server.listen(8888);server.start_accept();// 8. 启动服务器server.run();return 0;
}