本文已参加「新人创作礼」活动,一起敞开创作之路。
一、WebSocket++
WebSocket++是一个用于实现WebSocket功用的C++库。该库具有易于移植、轻量级和高性能的特色。
主要特色:
- 完好支撑 RFC6455
- 部分支撑 Hixie 76 / Hybi 00, 07-17规格草案(仅服务器)
- 基于消息/事情的接口
- 支撑安全的WebSockets(TLS)、IPv6和显式代理
- 灵敏的依赖性办理(C++11规范库或Boost)
- 可互换的网络传输模块(raw、iostream、Asio或自界说)
- 便携/跨平台(Posix/Windows,32/64位,Intel/ARM/PPC)
- 线程安全
官方库房
官方帮助文档
二、WebSocket++运用
2.1 准备环境
windows下编译boost 1.79
1、下载boost源码解压
2、进入vs指令行 x64 Native Tools Command Pro...
3、进入源码目录 cd boost_1_79_0
4、生成 b2.exe bootstrap.bat
5、编译全部 b2 -a
6、安装 b2 install
- 不安装也行,注意引用的位置
- (会安装到默许目录c:\Boost\,假如不想安装到默许目录可以用–prefix指定,详细可以用 b2 –help 检查)
注:关于windows平台,boost官方也供给编译好的二进制包
2.2 websocketpp库
1、websocketpp是一个c++的websocket库,下载解压后得到一下目录结构,其间websocketpp便是咱们所要用到的库文件,examples下有一些websocket的基本运用案例。
2、配置vs项目 boost与websocketpp两个库都是hpp的源码,只需求在附加包括目录里引入两个路径即可(确保include可以正常导入库文件)。一定要牢记:boost要最先导入,不然,会有各种莫名其妙的报错。
2.3 一些概念
从Websocketpp的例子中,拷贝需求用到的头文件包括和一些类型重界说
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>
using websocketpp::connection_hdl;
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind;
typedef websocketpp::server<websocketpp::config::asio> server;
typedef server::message_ptr message_ptr;
// 生成server目标
server m_server;
// 初始化m_server
m_server.set_access_channels(websocketpp::log::alevel::none); // 设置打印的日志等级
m_server.init_asio(); // 初始化asio
m_server.set_open_handler(bind(&XXXClass::on_open_func_ptr, this, ::_1)); // 绑定websocket衔接到来时的回调函数
m_server.set_close_handler(bind(&XXXClass::on_close_func_ptr, this, ::_1)); // 绑定websocket衔接断开时的回调函数
m_server.set_message_handler(bind(&XXXClass::on_message_func_ptr, this, ::_1, ::_2)); // 绑定websocket衔接有消息到来时的回调函数
上面三个回调函数的原型如下,我是将server目标直接封装到一个类里边运用的,因而这里绑定的回调函数可以直接运用类的方法。Websocketpp也供给了其他许多环节上的回调函数设定,可自行检查其源代码进行了解。
class XXXClass
{
public :
void on_open_func_ptr(connection_hdl hdl);
void on_close_func_ptr(connection_hdl hdl);
void on_message_func_ptr(connection_hdl hdl, message_ptr msg);
}
回调参数中的connection_hdl
是一个weak_ptr
,假如需求将衔接存到容器中以便办理,则不能运用传入的hdl
,需求运用
server::connection_ptr con = m_server.get_con_from_hdl(hdl);
取得的con
是个shared_ptr
,再调用
void *con_ptr = con->get();
可以得到这个衔接的实际目标的地址,但websocketpp对咱们隐藏了其目标的结构,只给了咱们一个void*
,不过用于在每次回调时区分不同的客户端足够了。
当websocket有新消息到来时,咱们可以通过
std::string msg_str = msg->get_payload();
直接获取到传输的内容。
以上,便是websocketpp集成后的简单运用流程,server目标其实还供给了许多的运用方法以及回调绑定功用,等有时间我再详细研讨,现在这几个现已能满足我的需求了。
2.4 展示
三、源码
客户端(指令窗口)
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>
#include <iostream>
typedef websocketpp::server<websocketpp::config::asio> server;
using websocketpp::lib::bind;
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
// pull out the type of messages sent by our config
typedef server::message_ptr message_ptr;
// Define a callback to handle incoming messages
void on_message(server *s, websocketpp::connection_hdl hdl, message_ptr msg)
{
std::string cmd = msg->get_payload();
std::string res = "fu wu qi de xin xi! \" ";
std::cout << "on_message called with hdl: " << hdl.lock().get()
<< " and message: " << msg->get_payload()
<< std::endl;
// check for a special command to instruct the server to stop listening so
// it can be cleanly exited.
if (msg->get_payload() == "stop-listening")
{
s->stop_listening();
return;
}
try
{
s->send(hdl, res, msg->get_opcode());
}
catch (websocketpp::exception const &e)
{
std::cout << "Echo failed because: "
<< "(" << e.what() << ")" << std::endl;
}
}
int main()
{
// Create a server endpoint
server echo_server;
try
{
// Set logging settings
echo_server.set_access_channels(websocketpp::log::alevel::all);
echo_server.clear_access_channels(websocketpp::log::alevel::frame_payload);
// Initialize Asio
echo_server.init_asio();
// Register our message handler
echo_server.set_message_handler(bind(&on_message, &echo_server, ::_1, ::_2));
// Listen on port 9002
echo_server.listen(9002);
// Start the server accept loop
echo_server.start_accept();
// Start the ASIO io_service run loop
echo_server.run();
}
catch (websocketpp::exception const &e)
{
std::cout << e.what() << std::endl;
}
catch (...)
{
std::cout << "other exception" << std::endl;
}
}
客户端(网页)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script>
function send(msg) {
var ws = new WebSocket("ws://localhost:9002");
ws.onopen = function (evt) {
console.log("Connection open ...");
ws.send(msg);
};
ws.onmessage = function (evt) {
console.log("Received Message: " + evt.data);
$("#show_txt").html(evt.data);
ws.close();
};
ws.onclose = function (evt) {
console.log("Connection closed.");
};
}
function send_msg() {
var msg = $("#in_msg").val();
send(msg);
}
</script>
<input type=text id="in_msg" style="width:800px;height:30px;" /><br />
<button onclick="send_msg()">发送信息</button><br />
输出:<div id="show_txt"></div>
</body>
</html>