websocketpp介绍

websocketpp是一个只有头文件的支持websocket协议的C++开源库,支持websocket客户端和服务器功能,网络传输模块基于boost::asio

提供 server 功能的 websocketpp::server 和提供 client 功能的 websocketpp:client 都继承自基类 websocketpp::endpoint , endpoint提供了一些通用的功能函数:

void set_access_channels(log::level channels);//设置日志级别
void clear_access_channels(log::level channels)//屏蔽某个级别的日志 void set_open_handler(open_handler h);//设置打开连接时的回调函数
void set_close_handler(close_handler h);//设置关闭连接时的回调函数
void set_fail_handler(fail_handler h);//设置连接失败时的回调函数
void set_message_handler(message_handler h);//设置收到消息时的回调函数

服务器代码

#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp> #include <functional> typedef websocketpp::server<websocketpp::config::asio> server; class utility_server {
public:
utility_server() {
// 设置log
m_endpoint.set_error_channels(websocketpp::log::elevel::all);
m_endpoint.set_access_channels(websocketpp::log::alevel::all ^ websocketpp::log::alevel::frame_payload); // 初始化Asio
m_endpoint.init_asio(); // 设置消息回调为echo_handler
m_endpoint.set_message_handler(std::bind(
&utility_server::echo_handler, this,
std::placeholders::_1, std::placeholders::_2
));
} void echo_handler(websocketpp::connection_hdl hdl, server::message_ptr msg) {
// 发送消息
m_endpoint.send(hdl, msg->get_payload(), msg->get_opcode());
} void run() {
// 监听端口 9002
m_endpoint.listen(9002); m_endpoint.start_accept(); // 开始Asio事件循环
m_endpoint.run();
}
private:
server m_endpoint;
}; int main() {
utility_server s;
s.run();
return 0;
}

运行后执行到 s.run() 当前线程会进入Asio的消息循环,可以调用s.top()退出

客户端代码

#include <websocketpp/config/asio_no_tls_client.hpp>
#include <websocketpp/client.hpp>
#include <iostream> typedef websocketpp::client<websocketpp::config::asio_client> client; using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind; typedef websocketpp::config::asio_client::message_type::ptr message_ptr; void on_open(client *c, websocketpp::connection_hdl hdl)
{
std::string msg = "hello";
c->send(hdl, msg, websocketpp::frame::opcode::text);
c->get_alog().write(websocketpp::log::alevel::app, "Tx: " + msg);
} void on_message(client *c, websocketpp::connection_hdl hdl, message_ptr msg)
{
std::cout << "on_message called with hdl: " << hdl.lock().get()
<< " and message: " << msg->get_payload()
<< std::endl;
websocketpp::lib::error_code ec;
//c->send(hdl,msg->get_payload(),msg->get_opcode(),ec);
if(ec)
{
std::cout << "Echo failed because " << ec.message() << std::endl;
}
} //定时器回调函数
void Timeout(client *c, websocketpp::connection_hdl &hdl, boost::asio::deadline_timer *pt, const boost::system::error_code &ec)
{
if(ec)
{
std::cout << "timer is cancel " << std::endl;
return;
}
static int count = 0;
c->send(hdl, "hello", websocketpp::frame::opcode::text);
count++;
if(count > 5)//定时器触发五次后关闭连接
{
c->close(hdl, websocketpp::close::status::normal, "");
return;
}
pt->expires_at(pt->expires_at() + boost::posix_time::seconds(5));
pt->async_wait(bind(Timeout, c, hdl, pt, ::_1)); } int main(int argc, char *argv[])
{
client c; std::string uri = "ws://xx.xx.xx.xx:xxx"; c.set_access_channels(websocketpp::log::alevel::all);
c.clear_access_channels(websocketpp::log::alevel::frame_payload);
c.clear_access_channels(websocketpp::log::alevel::frame_header); // 初始化 ASIO
c.init_asio(); // 注册消息回调 c.set_message_handler(bind(&on_message, &c, ::_1, ::_2));
c.set_open_handler(bind(&on_open, &c, _1)); websocketpp::lib::error_code ec;
client::connection_ptr con = c.get_connection(uri, ec);
con->add_subprotocol("janus-protocol");
if(ec)
{
std::cout << "could not create connection because: " << ec.message() << std::endl;
return 0;
} auto hdl = con->get_handle();
c.connect(con); boost::asio::deadline_timer t(c.get_io_service(), boost::posix_time::seconds(5)); //设置一个5s超时的定时器
t.async_wait(bind(&Timeout, &c, hdl, &t, ::_1)); std::thread th([&c] { c.run(); }); //休眠13s后取消定时器并关闭连接
sleep(13);
t.cancel();
c.close(hdl, websocketpp::close::status::normal, ""); th.join();
}

我们可以利用 Asio 的一些其它组件,如定时器等;初始化定时器传入 c.get_io_service() 在一个io循环中处理定时事件和其它事件

当客户端调用 close 关闭连接时,则自动退出c.run()开启的循环

重复关闭和打开连接

#include <websocketpp/config/asio_no_tls_client.hpp>
#include <websocketpp/client.hpp>
#include <iostream> typedef websocketpp::client<websocketpp::config::asio_client> client; using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2; typedef websocketpp::config::asio_client::message_type::ptr message_ptr;
class connection
{
public: void on_open(websocketpp::connection_hdl hdl)
{
std::string msg = "hello";
c.send(hdl, msg, websocketpp::frame::opcode::text);
c.get_alog().write(websocketpp::log::alevel::app, "Tx: " + msg);
} void on_message(websocketpp::connection_hdl hdl, message_ptr msg)
{
std::cout << "on_message called with hdl: " << hdl.lock().get()
<< " and message: " << msg->get_payload()
<< std::endl;
websocketpp::lib::error_code ec;
if(ec)
{
std::cout << "Echo failed because " << ec.message() << std::endl;
}
} int init()
{
uri = "ws://xx.xx.xx.xx:xx"; c.set_access_channels(websocketpp::log::alevel::all);
c.clear_access_channels(websocketpp::log::alevel::frame_payload);
c.clear_access_channels(websocketpp::log::alevel::frame_header); c.init_asio(); c.set_message_handler(websocketpp::lib::bind(&connection::on_message, this,::_1, ::_2));
c.set_open_handler(websocketpp::lib::bind(&connection::on_open, this, _1)); c.start_perpetual();
thread_=websocketpp::lib::make_shared<websocketpp::lib::thread>(&client::run,&c); } void connect()
{
websocketpp::lib::error_code ec;
client::connection_ptr con = c.get_connection(uri, ec);
if(ec)
{
std::cout << "could not create connection because: " << ec.message() << std::endl;
return ;
} hdl_ = con->get_handle();
c.connect(con); }
void close()
{
c.close(hdl_, websocketpp::close::status::normal, "");
} void terminate()
{
c.stop_perpetual();
thread_->join();
}
private:
client c;
websocketpp::lib::shared_ptr<websocketpp::lib::thread> thread_;
websocketpp::connection_hdl hdl_;
std::string uri; };

需要重复打开关闭连接时,只调用一次init_asio()函数,然后调用start_perpetual()将endpoint设置为永久的,不会在连接断开时自动退出。需要结束循环,调用stop_perpetual()

使用websocketpp进行websocket通信的更多相关文章

  1. C#(SuperWebSocket)与websocket通信

    原文:C#(SuperWebSocket)与websocket通信 客户端代码 点击可以查看一些关于websocket的介绍 <!DOCTYPE html> <html> &l ...

  2. js判断是否安装某个android app,没有安装下载该应用(websocket通信,监听窗口失去焦点事件)

    现在经常有写场景需要提示用户下载app, 但是如果用户已经安装,我们希望是直接打开app. 实际上,js是没有判断app是否已经安装的方法的,我们只能曲线救国. 首先,我们需要有call起app的sc ...

  3. Springboot集成WebSocket通信全部代码,即扣即用。

    websocket通信主要来自两个类以及一个测试的html页面. MyHandler 和 WebSocketH5Config,下面全部代码 MyHandler类全部代码: package com.un ...

  4. 【Java Web开发学习】Spring MVC整合WebSocket通信

    Spring MVC整合WebSocket通信 目录 ========================================================================= ...

  5. websocket通信1009错误,

    问题说明: springboot继承 WebSocketConfigurer实现websocket通信服务,服务器端报错,"The decoded text message was too ...

  6. Python3+WebSockets实现WebSocket通信

    一.说明 1.1 背景说明 前段时间同事说云平台通信使用了个websocket的东西,今天抽空来看一下具体是怎么个通信过程. 从形式上看,websocket是一个应用层协议,socket是数据链路层. ...

  7. webSocket通信

    针对webSocket通信总结: 1.webSocket通信原理图: 2.webSocket通信实例 参考地址1:https://www.cnblogs.com/cjm123/p/9674506.ht ...

  8. 把酒言欢话聊天,基于Vue3.0+Tornado6.1+Redis发布订阅(pubsub)模式打造异步非阻塞(aioredis)实时(websocket)通信聊天系统

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_202 "表达欲"是人类成长史上的强大"源动力",恩格斯早就直截了当地指出,处在蒙昧时代即低 ...

  9. websocket通信 实现java模拟一个client与webclient通信

    发文原由: 熟悉socket通信的同学,对于socket模拟server与client,实现相互通信, 或者使用websocket与java模拟的websocket服务器通信(比如一个聊天室),对于这 ...

随机推荐

  1. 利用sed将xml报文转换为分隔符形式报文

    原始xml文本如下 <?xml version="1.0" encoding="utf-8"?> <Message> <Heade ...

  2. Javascript实现10种排序算法

    1.冒泡排序: 比较相邻的两个数,如果前一个数大于后一个数,就将这两个数换位置.每一次遍历都会将本次遍历最大的数冒泡到最后.为了将n个数排好序,需要n-1次遍历.如果某次遍历中,没有调整任何两个相邻的 ...

  3. [网络流 24 题] luoguP2756 飞行员配对方案问题

    [返回网络流 24 题索引] 题目描述 英国皇家空军从沦陷国征募了大量外籍飞行员.由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的 222 名飞行员,其中 111 名是英国飞行员,另 ...

  4. [HDU2294] Pendant - 矩阵加速递推

    Pendant Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Sub ...

  5. nginx::基于Nginx+nginx-rtmp-module+ffmpeg搭建rtmp、hls流媒体服务器

    待续 ffmpeg -re -i "/home/bk/hello.mp4" -vcodec libx264 -vprofile baseline -acodec aac -ar 4 ...

  6. Spring Boot 2.X(十):自定义注册 Servlet、Filter、Listener

    前言 在 Spring Boot 中已经移除了 web.xml 文件,如果需要注册添加 Servlet.Filter.Listener 为 Spring Bean,在 Spring Boot 中有两种 ...

  7. php函数分为哪两种?

    PHP的真正威力源自于它的函数.函数分为内置函数和自定义函数. 内置函数 所谓PHP内置函数,就是在php程序的库里面已经定义了的函数,比如echo,mysql_connect,include_onc ...

  8. 案例_(单线程)使用xpath爬取糗事百科

    案例_(单线程)使用xpath爬取糗事百科 步骤如下: 首先通过xpath插件找出我们要爬取的信息的匹配规则 url = "https://www.qiushibaike.com/8hr/p ...

  9. 算法问题实战策略 DICTIONARY

    地址 https://algospot.com/judge/problem/read/DICTIONARY 解法 构造一个26字母的有向图 判断无回路后 就可以输出判断出来的字符序了 比较各个字母的先 ...

  10. vue-cli2、vue-cli3脚手架详细讲解

    前言: vue脚手架指的是vue-cli它是vue官方提供的一个快速构建单页面(SPA)环境配置的工具,cli 就是(command-line-interface  ) 命令行界面 .vue-cli是 ...