websocketpp是一个基于C11标准开发的websocket c++框架,文档地址为https://docs.websocketpp.org/getting_started.html,源码地址为https://github.com/zaphoyd/websocketpp(经常打不开)。
典型使用方法如下代码,额外应该加上多线程,在主线程中针对每个客户端管理其活跃时间,定期清理不活跃的客户端。
#include <iostream>
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>
typedef websocketpp::server<websocketpp::config::asio> WebsocketServer;
typedef WebsocketServer::message_ptr message_ptr;
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind;
using namespace std;
WebsocketServer server;
void OnOpen(WebsocketServer *server, websocketpp::connection_hdl hdl)
{
WebsocketServer::connection_ptr con = server->get_con_from_hdl(hdl);
string client_ip_port = con->get_remote_endpoint();
cout << "have client connected: " << client_ip_port << endl;
}
void OnClose(WebsocketServer *server, websocketpp::connection_hdl hdl)
{
WebsocketServer::connection_ptr con = server->get_con_from_hdl(hdl);
string client_ip_port = con->get_remote_endpoint();
cout << "have client disconnected: " << client_ip_port << endl;
}
void OnMessage(WebsocketServer *server, websocketpp::connection_hdl hdl, message_ptr msg)
{
string strMsg = msg->get_payload();
string strRespon = "receive: " + strMsg;
try {
WebsocketServer::connection_ptr con = server->get_con_from_hdl(hdl);
string client_ip_port = con->get_remote_endpoint();
cout << strRespon " from " << client_ip_port << endl;
server->send(hdl, strRespon, websocketpp::frame::opcode::text);
} catch (websocketpp::exception const &e) {
cout << "error: " << e.what() << endl;
}
}
bool OnPing(WebsocketServer *server, websocketpp::connection_hdl hdl, std::string payload) {
server->get_alog().write(websocketpp::log::alevel::app, payload);
WebsocketServer::connection_ptr con = server->get_con_from_hdl(hdl);
string client_ip_port = con->get_remote_endpoint();
cout << "recv ping: " << payload " from " << client_ip_port << endl;
try {
server->pong(hdl, "pong");
} catch (websocketpp::exception const &e) {
cout << "error: " << e.what() << endl;
}
return false;
}
bool OnPong(WebsocketServer *server, websocketpp::connection_hdl hdl, std::string payload) {
server->get_alog().write(websocketpp::log::alevel::app, payload);
WebsocketServer::connection_ptr con = server->get_con_from_hdl(hdl);
string client_ip_port = con->get_remote_endpoint();
cout << "recv pong from " << client_ip_port << ": " << payload << endl;
return false;
}
// js客户端连接方式:var ws = new WebSocket("ws://xxxxx", ["token value"]);
bool OnValidate(WebsocketServer *server, websocketpp::connection_hdl hdl)
{
WebsocketServer::connection_ptr con = server->get_con_from_hdl(hdl);
string client_ip_port = con->get_remote_endpoint();
string key = "Sec-WebSocket-Protocol";
string token = con->get_request_header(key);
std::cout << key << ": " << token << std::endl;
if (0) { // 不满足条件时直接返回FALSE,客户端会收到4类错误连接不上
return false;
}
// 验证通过添加头部并返回true
con->append_header(key, token); // 以后回复数据都要加这个头部信息
return true;
}
int main() {
server.set_reuse_addr(true); // 设置套接字选项SO_REUSEADDR
// Set logging settings
server.set_access_channels(websocketpp::log::alevel::all);
server.clear_access_channels(websocketpp::log::alevel::frame_payload);
// Initialize ASIO
server.init_asio();
server.set_ping_handler(bind(&OnPing, &server,::_1,::_2));
server.set_pong_handler(bind(&OnPong, &server,::_1,::_2));
// Register our open handler
server.set_open_handler(bind(&OnOpen, &server, ::_1));
// Register our close handler
server.set_close_handler(bind(&OnClose, &server, _1));
// Register our message handler
server.set_message_handler(bind(&OnMessage, &server, _1, _2));
// 连接验证
server.set_validate_handler(bind(&OnValidate, &server, ::_1));
//Listen on port 2152
unsigned short port = 98;
try {
server.listen(port);
cout << "listen at " << port << endl;
//Start the server accept loop
server.start_accept();
//Start the ASIO io_service run loop
server.run();
} catch (websocketpp::exception const &e) {
cout << "error: " << e.what() << endl;
}
return 0;
}