WebSocketPP常见问题解答与技术指南
websocketpp C++ websocket client/server library 项目地址: https://gitcode.com/gh_mirrors/we/websocketpp
概述
WebSocketPP是一个功能强大的C++ WebSocket库,为开发者提供了构建WebSocket客户端和服务器的完整工具集。本文将深入解析该库使用过程中的常见问题和技术要点,帮助开发者更好地理解和应用这个库。
核心使用问题
连接建立后修改或移除处理器
在WebSocketPP中,端点(Endpoint)上设置的处理器会被自动复制到该端点创建的所有连接中。修改端点上的处理器只会影响后续创建的连接。
对于已建立的特定连接,可以通过调用set_*_handler
方法单独修改其处理器。修改后,该连接后续所有该类型事件都将使用新的处理器。
如果需要移除已设置的处理器,只需将处理器设置为nullptr
或NULL
即可。
连接接受与拒绝机制
WebSocketPP提供了灵活的连接验证机制。validate
处理器在完成初始握手但尚未响应时被调用,开发者可以在此检查连接请求、头信息、来源、子协议和远程端点IP等信息。
返回true
接受连接,返回false
拒绝连接。拒绝时还可以通过websocketpp::connection::set_status
设置自定义HTTP错误状态码,以及使用websocketpp::connection::set_body()
设置错误消息正文。
子协议协商机制
WebSocket连接可以协商使用特定的子协议。WebSocketPP服务器可以在validate
处理器中通过websocketpp::connection::get_requested_subprotocols
读取客户端请求的子协议列表(按客户端优先级排序),并通过websocketpp::connection::select_subprotocol
选择其中一个子协议。
客户端在建立连接前可以通过websocketpp::connection::add_subprotocol
添加子协议,添加顺序将被解释为优先级顺序。
连接建立后,可通过websocketpp::connection::get_subprotocol
获取最终选择的子协议。
使用Asio传输时的优雅退出
使用Asio传输的客户端和服务器依赖于Asio的io_service
处理异步网络操作。要实现优雅退出:
- 服务器调用
websocketpp::transport::asio::endpoint::stop_listening
关闭监听套接字 - 如果客户端启用了永久模式(
start_perpetual
),需调用stop_perpetual
禁用 - 对所有活动连接调用
close
方法 - 等待异步操作完成
重要警告:避免直接使用io_service::stop
或endpoint::stop
,这会中断所有操作,可能导致套接字处于不稳定状态。
连接句柄有效性检查
WebSocketPP提供了有限的连接句柄有效性检查机制:
- 尝试通过
websocketpp::endpoint::get_con_from_hdl
将句柄升级为完整连接指针 - 如果升级失败,则句柄肯定无效
- 如果升级成功,仍需通过实际发送操作(消息或ping)确认连接有效性
服务器重启时的"地址已使用"错误
操作系统通常防止程序监听其他程序创建的套接字。程序崩溃重启后,新实例被视为不同程序,必须等待超时才能重用原地址/端口。
解决方案:
- 实现干净的服务器关闭机制
- 考虑使用SO_REUSEADDR套接字选项(通过
websocketpp::transport::asio::endpoint::set_reuse_addr
设置)
注意:在共享资源环境中,不独占锁定监听套接字可能带来安全风险。
二进制消息处理
WebSocketPP支持RFC6455定义的两种消息格式:UTF-8文本和二进制。对于传入消息,使用websocketpp::message_buffer::message::get_opcode
确定类型(websocketpp::frame::opcode::text
或websocketpp::frame::opcode::binary
)。
发送消息时,可通过send
方法的第二个参数指定类型。有两个主要重载版本:
- 接受
std::string
,默认为文本类型 - 接受
void const*
和size_t
长度,默认为二进制类型
依赖管理
无Boost环境使用
WebSocketPP仅在缺少C++11功能时使用Boost作为替代。如果使用C++11或更高标准的编译器和标准库,可以无需Boost。
对于iostream/raw传输,C++11标准库已足够。对于Asio传输,即使使用C++11构建系统,仍需要独立的Asio库(如果Boost Asio不可用)。
独立Asio使用
定义ASIO_STANDALONE
后即可使用独立Asio。需要单独下载Asio头文件并确保其在构建系统的包含路径中。
无TLS/OpenSSL使用
使用iostream/raw传输时无需TLS功能。使用Asio传输时TLS功能是可选的,仅当需要加密连接时才需要OpenSSL。
是否使用TLS由配置模板参数决定。默认的websocketpp::config::asio
和websocketpp::config::asio_client
配置不支持TLS,而websocketpp::config::asio_tls
和websocketpp::config::asio_tls_client
支持。
OS X上的TLS构建问题
Mac OS X自带的OpenSSL版本较旧。要安全使用TLS,需要通过Homebrew或源码编译安装现代版OpenSSL。
MinGW兼容性
MinGW在C++11模式下目前不支持C++11 STL <thread>
库。WebSocketPP需要线程/互斥库,选项包括Boost线程或mingw-std-threads
。
压缩功能
0.6.0-permessagedeflate和0.7.0版本的permessage-deflate使用
这些版本需要通过自定义配置使用permessage-deflate扩展。示例配置如下:
服务器配置示例:
#include <websocketpp/extensions/permessage_deflate/enabled.hpp>
struct deflate_server_config : public websocketpp::config::asio {
struct permessage_deflate_config {};
typedef websocketpp::extensions::permessage_deflate::enabled
<permessage_deflate_config> permessage_deflate_type;
};
typedef websocketpp::server<deflate_server_config> server_endpoint_type;
客户端配置示例:
#include <websocketpp/extensions/permessage_deflate/enabled.hpp>
struct deflate_client_config : public websocketpp::config::asio_client {
struct permessage_deflate_config {};
typedef websocketpp::extensions::permessage_deflate::enabled
<permessage_deflate_config> permessage_deflate_type;
};
typedef websocketpp::client<deflate_client_config> client_endpoint_type;
在这些版本中,压缩是自动协商的,默认情况下会压缩所有消息,但可以强制特定消息不压缩。
安全相关
恶意连接的快速终止
WebSocketPP会自动检测并终止违反WebSocket协议的连接。对于被认为恶意或严重损坏的连接,将省略关闭握手。
应用程序可以在协议层面之上检测恶意条件,并使用特殊关闭代码立即终止连接:
websocketpp::close::status::omit_handshake
:省略关闭握手,但干净地关闭TCP连接websocketpp::close::status::force_tcp_drop
:强制丢弃TCP连接
注意:这些方法违反了WebSocket协议,可能对远程端点造成负面影响,应谨慎使用。
构建问题
与计时相关的编译错误
如果遇到与std::chrono
、boost::chrono
、waitable_timer
或steady_clock
相关的编译错误,可能是构建系统混淆了boost::chrono
和std::chrono
的使用。定义BOOST_ASIO_HAS_STD_CHRONO
可能有助于解决此问题。
通过本文的详细解析,开发者可以更全面地理解WebSocketPP库的各种特性和使用场景,从而在实际项目中做出更合理的技术决策和实现。
websocketpp C++ websocket client/server library 项目地址: https://gitcode.com/gh_mirrors/we/websocketpp
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考