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;
}


Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐