C++下跨平台websocket库及使用示例

websocketpp库使用非常方便,开源,可跨平台,内部实现全部是head文件,无cpp,接口简单易用。源码路径比如 https://github.com/zaphoyd/websocketpp.git

使用方法是,先下载源码包并复制道工程的include目录下。

--include

   --websocketpp

然后在代码#include "utility_client.hpp"即可调用其接口进行websocket通信。以linux为例具体使用的方法代码示例:

websockettalker.h:

#ifndef WEBSOCKETTALKER_H
#define WEBSOCKETTALKER_H
#include "dao.h"
#include "utility_client.hpp"
#include "pthread.h"
#include "vector"

using namespace std;
class CloudTalker;
class WebsocketTalker
{
public:
	WebsocketTalker(CloudTalker* talker, const string& remoteAddr, const string& name);
	~WebsocketTalker();
	string GetStatus();
	string GetMessage();
	bool Subscribe(const string& deviceId, const string& token);
	void handleNbData(const string& msg);

private:
	CloudTalker* mTalker;
	static void* thread_loop(void* pVoid);
	pthread_t recv_thread;
	websocket_endpoint mEndpoint;
	int mId;
	string addr = "";
	bool should_exit = false;
    vector<DevInfo> mImeiTable;
    DAO* mDevDbDao = NULL;
};

#endif // WEBSOCKETTALKER_H

websockettalker.cpp:

#include "websockettalker.h"
#include "cloudtalker.h"
#include "udptalker.h"
#include <boost/algorithm/string.hpp>

using namespace boost;
#define JSON_PATH_DEV "path/to/devDB.json"
WebsocketTalker::WebsocketTalker(CloudTalker* talker, const string& remoteAddr, const string& name)
{
	string messageclient;
	addr = "ws://" + remoteAddr + ":8081/webSocketServer?" + name; //格式为
	cout <<"full address is:" <<addr <<endl;
	mTalker = talker;
    mDevDbDao = new DAO();
	pthread_create(&recv_thread, nullptr, thread_loop, this);
}

/***********************************************************
* 描述: 处理数据
* 入参: wholeMsg - 要处理的数据
* 出参: 无
* 返回: 无
************************************************************/
void WebsocketTalker::handleData(const string& wholeMsg)
{

	cout <<endl;

}



/***********************************************************
* 描述: websocket通信线程
* 入参: pVoid - WebsocketTalker指针
* 出参: 无
* 返回: 无
************************************************************/
void* WebsocketTalker::thread_loop(void* pVoid)
{
	WebsocketTalker* p = (WebsocketTalker*) pVoid;
	string status = "";
	string wholeMsg = "";
	int cont = 0;
    unsigned int len = 0;
	while(!p->should_exit)
	{
        p->mImeiTable.clear();
		printf("WEBSOCKET WANT TO CREATE CONNECT FOR NBIOT DATA\n");
        p->mDevDbDao->getNBAndShareImeiAll(JSON_PATH_DEV, p->mImeiTable);
        len = p->mImeiTable.size();
        if(len == 0)
        {
            int cnt = 0;
            printf("nb/share dev list is zero\n");
            while(!p->should_exit && cnt++ <4)
            {
                usleep(500000);
            }
            cnt = 0;
            continue;
        }
		p->mId = p->mEndpoint.connect(p->addr);
		if (p->mId == -1)
		{
			cout << "Created connection failed! mId=" << p->mId<< endl;
		}
		else
		{
			while(!p->should_exit)
			{
				usleep(50000);

				status = p->GetStatus();
				if(status.length() && status != "Connecting")
					break;
			}
			if(p->should_exit)
			{
				printf("exit 1\n");
				break;
			}
            for(unsigned int i=0; i<len; i++)
            {
                cout<<"subscribe dev: " << p->mImeiTable[i].IMEi<< "with token: "<<p->mImeiTable[i].Token<<endl;
                p->Subscribe(p->mImeiTable[i].IMEi, p->mImeiTable[i].Token);
                cont = 0;
                while(!p->should_exit)
                {
                    usleep(50000);

                    status = p->GetStatus();
                    if(status == "Message")
                        break;
                    if(cont++ > 40)
                    {
                        printf("websocket data receive subscribe status timeout\n");
                        //cont = 0;
                        break;
                    }
                }
                if(p->should_exit || cont > 40)
                {
                    printf("exit 2\n");
                    break;
                }
                wholeMsg = p->GetMessage();
                printf("[%s(%d)%s] msg=%s\n", __FUNCTION__, __LINE__, __TIME__, wholeMsg.data());
                cont = 0;
                /*循环接收消息 */
                while(!p->should_exit)
                {
                    if(cont++ > 40)
                    {
                        printf("websocket data receive timeout\n");
                        //cont = 0;
                        break;
                    }
                    status = p->GetStatus();
                    //printf("get status: %s\n", status.c_str());
                    if(status == "Message")
                    {
                        wholeMsg = p->GetMessage();
                        printf("[%s(%d)%s;] GOT SUBSCRIBED DATA, msg=%s\n", __FUNCTION__, __LINE__, __TIME__, wholeMsg.data());
                        p->handleNbData(wholeMsg);
                        cont = 0;
                        break;
                    }
                    usleep(50000);
                }
                if(p->should_exit)
                {
                    printf("exit 3\n");
                    break;
                }

            }
			p->mEndpoint.close(p->mId, websocketpp::close::status::normal, "close");
			if(p->should_exit)
			{
				printf("exit 3\n");
				break;
			}
		}
		usleep(2000000);//sleep long time could be.
	}

	return NULL;
}
string WebsocketTalker::GetStatus()
{
	return mEndpoint.get_metadata(mId)->get_status();
}

string WebsocketTalker::GetMessage()
{
	return mEndpoint.get_metadata(mId)->get_message();
}


bool WebsocketTalker::Subscribe(const string& deviceId, const string& token)
{
	string str;

	str = "{\"type\":\"address\",\"msg\":\"" + deviceId + "\",\"token\":\"" + token +"\"}";
	printf("[%s(%d)] %s\n", __FUNCTION__, __LINE__, str.data());
	mEndpoint.send(mId, str);

	return true;
}


WebsocketTalker::~WebsocketTalker()
{
	printf("exit wstalker\n");
    if(mDevDbDao != NULL)
    {
        delete mDevDbDao;
    }
	should_exit = true;
	pthread_join(recv_thread, NULL);
	printf("exit wstalker done\n");
}


 dao.h:

#ifndef DAO_H
#define DAO_H

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include "json/json.h"

#ifndef UNUSED
#define UNUSED(x) (void)(x)
#endif

using namespace std;

typedef struct
{
    string IMEi;
    string Type;
    string Token;
}DevInfo;


class DAO{

public:
    DAO(){}

    // 10. get device information transform to <vector> from json, "device information contain {IMEI, type, token, index}"
    int getNBAndShareImeiAll(const char* dfile_path, vector<DevInfo>& imeiTable)
    {
        fstream dev_f;
        dev_f.open(dfile_path, ios::in | ios::out);
        if (!dev_f.is_open())
        {
            cout << "Open file error !" << endl;
        }

        Json::Value val;
        Json::Value root_arr;
        JSONCPP_STRING errs;
        //bool did;
        DevInfo devInfo;

        Json::CharReaderBuilder rbuilder;
        rbuilder["collectComments"] = false;
        bool parse_ok = Json::parseFromStream(rbuilder, dev_f, &root_arr, &errs);

        if(!parse_ok)
        {
            cout << "Parse json file error !" << endl;
        }
        else
        {
            const Json::Value arrayObj = root_arr;
            cout << " ------ Printf Device information: ------ " << endl;
            try
            {
                for (unsigned int i = 0; i < arrayObj.size(); i++)
                {
                    if(arrayObj[i]["Type"].asString() == "LORA")
                    {
                        devInfo =
                                {
                                 arrayObj[i]["IMEi"].asString(),
                                 arrayObj[i]["Type"].asString(),
                                 arrayObj[i]["Token"].asString()
                                };
                        imeiTable.push_back(devInfo);
                    }
                }
            }
            catch (const Json::LogicError &ex)
            {
                cout << " Parse json string error!" << endl;
            }
        }

        dev_f.close();

        return 0;
    }

};



#endif // DAO_H

 devDB.json:

[
	{
		"IMEi" : "6789999",
		"Token" : "jfkl",
		"Type" : "LORA"
	},
	{
		"IMEi" : "00124b00",
		"Token" : "0",
		"Type" : "xxx"
	},

]

json的解析使用jsoncpp库,可自行安装。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/579505.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

yolov8 dll 编译

1. 每次用yolo v8 都要用python &#xff0c;对于我这种写软件的太不方便了&#xff0c;下面尝试编译dll 调用, 我已经有做好的模型.best.pt 参考视频方法: yolov8 TensorRT C 部署_哔哩哔哩_bilibili 【yolov8】tensorrt部署保姆级教程&#xff0c;c版_哔哩哔哩_bilibili 需…

怎么做视频二维码更方便?在线一键生成视频活码二维码

现在经常会发现很多的二维码可以用来展示视频内容&#xff0c;通过这种方式来实现视频的快速分享与传播。二维码是一种成本低传播快的内容传播方式&#xff0c;很多的内容都可以通过生成二维码的方式来分享给其他人&#xff0c;可以同时扫描相同的二维码来获取内容&#xff0c;…

电脑的无用设置功能(建议关闭)

目录 1、传递优化 ​2、常规​ 3、电源 1、传递优化 2、常规3、电源

Vue2和Vue3的生命周期对比

beforeCreate 、created 两个钩子被setup()钩子来替代。 所有生命周期前面加了on

【Kotlin】Channel简介

1 前言 Channel 是一个并发安全的阻塞队列&#xff0c;可以通过 send 函数往队列中塞入数据&#xff0c;通过 receive 函数从队列中取出数据。 当队列被塞满时&#xff0c;send 函数将被挂起&#xff0c;直到队列有空闲缓存&#xff1b;当队列空闲时&#xff0c;receive 函数将…

PotatoPie 4.0 实验教程(41) —— FPGA实现RISC-V 扩展 GPIO UART Timer功能

TD工程介绍 我们提供的TD工程里的RISC-V核默认就开启了GPIO UART扩展&#xff0c;可以看到还有SPI和I2C扩展。因此后面的实验中TD的工程我们基本不怎么修改TD的内容&#xff0c;只需要修改TD工具中Soc_Top.v文件中的TCM0_INITFILE为FD生成的固件名称即可&#xff0c;主要修我以…

数据集市的详细建设方案!

▶ 什么是数据集市&#xff1f; 数据集市是处理单一事务的数据仓库的子集。它们通常由单个业务部门构建和管理。由于它们是面向主题的&#xff0c;因此通常仅从少数来源获取数据&#xff0c;这些来源可能是内部操作系统&#xff0c; 数据湖&#xff0c;一个集中的 数据存储库&a…

c++理论篇(一) ——浅谈tcp缓存与tcp的分包与粘包

介绍 在网络通讯中,Linux系统为每一个socket创建了接收缓冲区与发送缓冲区,对于TCP协议来说,这两个缓冲区是必须的.应用程序在调用send/recv函数时,Linux内核会把数据从应用进程拷贝到socket的发送缓冲区中,应用程序在调用recv/read函数时,内核把接收缓冲区中的数据拷贝到应用…

Android 设置头像 - 相册拍照

Android开发在个人信息管理中&#xff0c;如果设置头像&#xff0c;一般都提供了从相册选择和拍照两种方式。下午将针对设置用户头像相册和拍照两种方式的具体实现进行详细说明。 在实际实现过程中需要使用到权限管理&#xff0c;新版本的Android需要动态申请权限&#xff0c;权…

rabbitmq下载安装最新版本--并添加开机启动图文详解!!

一、简介 RabbitMQ是一个开源的遵循AMQP协议实现的消息中间件支持多种客户端语言,用于分布式系统中存储和转发消息, 这是 Release RabbitMQ 3.13.0 rabbitmq/rabbitmq-server GitHub 二、安装前准备 1、查看自己系统 确认操作系统版本兼容性 uname -a2、下载Erlang依赖包…

【12580无线通信技术】第十一章 Ad hoc网络无线通信技术期末复习自考复习

第十一章 Ad hoc网络无线通信技术 P283&#xff08;名词&#xff09;Ad hoc技术&#xff1a;是一种特定的无线网络结构&#xff0c;强调的是多跳、自组织、无中心的概念。P285&#xff08;简答&#xff09;Ad hoc网络的特点:①自组织和无中心特性&#xff1b;②网络拓补动态变…

SpringCloud系列(20)--Ribbon的简介及使用

1、Ribbon的简介 Spring Cloud Ribbon是基于Netflix Ribboh实现的一套客户端负载均衡的工具&#xff0c;简单的说&#xff0c;Ribbon是Netflix发布的开源项目&#xff0c;主要功能是提供客户端的软件负载均衡算法和服务调用。Ribbon客户端组件提供一系列完善的配置项如连接超时…

学习100个Unity Shader (14) ---透明效果

文章目录 渲染队列透明度测试&#xff08;Alpha Test&#xff09;效果Shader 透明度混合&#xff08;Alpha Blending&#xff09;效果Shader 参考 渲染队列 由”Queue“ 标签决定&#xff0c;索引号越小越早被渲染&#xff1a; 名称队列索引号Background1000Geometry2000Alph…

论文阅读之MMSD2.0: Towards a Reliable Multi-modal Sarcasm Detection System

文章目录 论文地址主要内容主要贡献模型图技术细节数据集改进多视图CLIP框架文本视图图像视图图像-文本交互视图 实验结果 论文地址 https://arxiv.org/pdf/2307.07135 主要内容 这篇文章介绍了一个名为MMSD2.0的多模态讽刺检测系统的构建&#xff0c;旨在提高现有讽刺检测系…

通过大模型(LLM)的多模态辩论的恶意表情包识别

Towards Explainable Harmful Meme Detection through Multimodal Debate between Large Language Models https://arxiv.org/abs/2401.13298https://arxiv.org/abs/2401.13298 1.概论 对于恶意表情包的识别,以往的研究方法没有能够深入表情包所隐含的复杂意义和文化背景,因…

vue-manage-system 更新,后台管理系统开发更简单

vue-manage-system 近期进行了一次版本升级&#xff0c;主要是支持了更多功能、升级依赖版本和优化样式&#xff0c;并且上线了官方文档网站&#xff0c;大部分功能都有文档或者使用示例&#xff0c;更加适合新手上手开发&#xff0c;只需要根据实际业务简单修改&#xff0c;就…

用fgets()替换fscanf()解决文件读取在小熊猫C++失败问题

fscanf&#xff08;&#xff09;遇到空格就结束读取&#xff0c;导致文件读取数据没完就退出读取以至于不能导入游戏地图工程。 看看到右侧小方块轨迹知晓采样区移动情况 也已经实现摄像机追随玩家效果 // 程序&#xff1a;2D RPG 地图编辑器与摄像机追随 // 作者&#xff1…

C语言自定义类型【联合体与枚举】

文章目录 1.联合体1.1联合体的声明1.2联合体的特点1.3联合体的大小计算联合体的使用案例 2.枚举2.1枚举类型的声明2.2枚举类型的优点(为什么使用枚举)2.3枚举类型的使用 结语 1.联合体 1.1联合体的声明 和结构体一样&#xff0c;联合体也是由一个或多个成员构成&#xff0c;同…

如何在 Visual Studio 中通过 NuGet 添加包

在安装之前要先确定Nuget的包源是否有问题。 Visual Studio中怎样更改Nuget程序包源-CSDN博客 1.图形界面安装 打开您的项目&#xff0c;并在解决方案资源管理器中选择您的项目。单击“项目”菜单&#xff0c;然后选择“管理 NuGet 程序包”选项。在“NuGet 包管理器”窗口中…

CTF(web方向)--md5的“===”和“==”的绕过

一、PHP弱类型说明 1.简介 php是一种弱类型语言&#xff0c;对数据的类型要求并不严格&#xff0c;可以让数据类型互相转换。 在php中有两种比较符号: 一种是 &#xff0c;另外一种是 &#xff0c;都是用来比较两个数值是否相等的操作符&#xff0c;但他们也是有区别的: &a…