kizumi_header_banner_img

Learn. Build. Share.

加载中

文章导读

基于脚手架微服务的视频点播系统-脚手架开发部分-jsoncpp,protobuf,Cpp-httplib与WebSocketpp中间件介绍与使用


avatar
xiu114514 2025年10月6日 179
基于脚手架微服务的视频点播系统-脚手架开发部分-jsoncpp,protobuf,Cpp-httplib与WebSocketpp中间件介绍与使用

@TOC

一.JSON

1.1JSON简介

JSON(JavaScript Object Notation)是⼀种轻量级的数据交换格式,易于⼈阅读和编写,同时也易于机器解析和⽣成。它基于JavaScript的⼀个⼦集,但尽管它来源于JavaScript,JSON是独⽴于语⾔的,可以被多种编程语⾔读取。以下是关于JSON的⼀些关键点: 基本结构: 对象:由键值对组成,⼤括号 {} 包围。 数组:由值的有序集合组成,⽅括号 [] 包围。 值:可以是字符串、数字、对象、数组、布尔值( true / false )或 null 。 语法规则: 键值对以 "key": value 的形式出现,键和值之间⽤冒号 : 分隔。 多个键值对之间⽤逗号 , 分隔。 所有键都必须是字符串,并且⽤双引号 " 包围。

1.2简单示例

因为之前我们在介绍序列化与反序列化时已经用到过json了,这里我们就不去再说它的用途什么的了。直接给一个简单的报文示例:

1.3JSONCPP简介

1.3.1安装

1.3.2使用

使用时需要包含头文件:

同时需要连接库:

1.3.3数据转储相关

1.3.4序列化相关

1.3.5反序列化相关

1.4二次封装及简单使用示例

Jsoncpp序列化流程

创建StreamWriterBuilder配置序列化参数(如缩进格式),通过newStreamWriter()生成写入器。写入器将Json::Value对象输出到字符串流,若写入成功则返回字符串形式,失败返回空值。

Jsoncpp反序列化流程

创建CharReaderBuilder并生成解析器,通过parse()方法将JSON字符串解析为Json::Value对象。解析失败时返回错误信息,成功则返回解析后的数据结构。

所以我们可以得到如下封装:

然后我们编写一个测试示例:

运行结果如下:

二.Protobuf

之后我们会对protobuf进行详细的介绍与使用,这里我们先来简单的了解下,给他使用起来即可。

2.1Protobuf简介

Protobuf 是Google 开发的⼀种轻便、⾼效的结构化数据存储/交换格式,类似于 XML 或 JSON,但⽐它们更⼩、更快、更简单。Protobuf 定义了⼀种接⼝描述语⾔(IDL),⽤于描述数据结构,然后以⾃动⽣成各种编程语⾔的代码来操作这些数据结构。

2.2Protobuf的用途与特性

数据序列化:⽤于⽹络通信、数据存储等场景,将数据结构序列化为字节流。 跨语⾔服务:由于 Protobuf ⽀持多种编程语⾔,它⾮常适合构建跨语⾔的 RPC(远程过程调⽤)服务。 数据兼容性:Protobuf 通过版本控制机制,可以向后兼容旧的数据格式。

2.3安装

2.4基本语法

我们通过一个简单的例子作以说明:

1.描述语法版本:syntax = "proto3"; 2.声明包名称:package example;在C++中的体现就是命名空间的名称 3.开启rpc服务:option cc_generic_services = true; 4.定义枚举字段,编号必须从0开始。 5.定义消息类型Message,字符串–string,整型–int32,浮点型–float,键值对–map<int32,string>,数组repeated int32。

2.5编译

2.6向message中的字段进行数据的设置/获取/清除

经过protoc的编译后针对上面的例子会生成两个文件:person.pb.h与person.pb.cc。我们先不提rpc服务相关的接口,我们到后面介绍brpc时再去介绍。这里我们先来说下Protobuf的序列化与反序列化相关的接口: 各个字段相关如果是普通字段(非数组或map),它的使用方法跟我们标准库中的一般没有区别,比如与name字段和id字段的在person.pb.h中的相关部分:

根据字面意思我们便可以知道他们有设置方法set,清除方法clear以及获取字段内容的name()与id()方法,这些都是最常见的使用方法。 对于枚举字段其实也大差不差:

也是设置,清除和获取三个方法。 但是对于数组类型我们看:

去除private部分:

也是设置添加和清空,但是他都是从尾部进行添加的,也就是它的add_scores类似于vector的push_back。当然他也可以去获取数组的指针进行添加也就是上面的后两个方法,一个是获取 const指针,一个是获取非const数组指针,使用后者进行添加:

而对于键值对: 去掉private部分:

它好像只有清空和获取元素个数这两个接口,没用增加元素接口啊,有的。只不过需要通过上面的最后一个方法获取map的指针对象,然后才能通过insert向键值对中增加数据:

那么在这里我们看一下protobuf底层实际的map相关接口:

2.7Message中提供的序列化与反序列化接口

在protobuf中定义的每个message结构,在编译后都会⽣成⼀个继承于Message类的派⽣类,其内部包含了消息中各个字段的操作接⼝,但是除了这些操作接⼝外,我们还需要了解⼀下这些消息结构所⽣成的派⽣类中继承⽽来的其他操作:

2.8Protobuf中的工具类

protobuf中的⼯具操作有很多,当前仅贴出了⽤于protobuf和json(另⼀种⾮常流⾏的序列化⽅式,详细了解可以看看脚⼿架的关于jsoncpp的使⽤⽂档)之间的转换接⼝。

2.9样例

我们基于上面的接口介绍来写一段protobuf的序列化和反序列化,以及protobuf转json和json转protobuf的示例:

makefile:

运行之后我们能看到如下结果:

由于protobuf序列化生成的是纯二进制数据,因此初始序列化结果显示为乱码。

三.Cpp-httplib

C++ HTTP 库(cpp-httplib)是⼀个轻量级的C++ HTTP 客⼾端/服务器库,它提供了简单的 API 来创建 HTTP 服务器和客⼾端,⽀持同步和异步操作。它的使用非常简单。 cpp-httplib 有⼀个活跃的社区,最近一次更新是几天前,有兴趣的读者可以去github上搜索Cpp-httplib,第一个就是我们本项目中用到的这个三方库。

3.1安装

3.2使用

它的使用安装之后不需要连接任何的三方库,只需要包含头文件:

即可直接使用。 它的接口定义也非常清晰明了,核心接口与相关类如下:

它的实现原理可以由一张图进行概况: 在这里插入图片描述

3.3使用样例

makefile:

运行后我们用浏览器访问http://你的服务器ip:9000/hi或者/1232131等任意数字都会呈现如下图所示的界面: 在这里插入图片描述 控制台输出:

四.websocket

4.1基本认识

我们都知道,一次http请求大致是如下的流程: 在这里插入图片描述 也就是说,如果接下来服务端想要找到客户端发送消息给他,此时服务端就找不到原来的客户端了。比如我们平时通信的场景: 在这里插入图片描述 那有人说让客户端发起多次http请求,不断去询问服务端有没有新消息不就ok了。显然是不可以的,第一个原因便是占用资源多,第二个原因便是不够实时。所以短连接是无法达成这个目标的。此时我们就需要使用websocket协议:长连接通信来达到服务端能够主动给客户端发消息的目的。它的大致流程如下: 在这里插入图片描述 具体协议升级的过程如下: 在这里插入图片描述 它的报文格式如下: 在这里插入图片描述 字段比较多,我们只关注几个比较主要的字段: FIN: WebSocket传输数据以消息为概念单位,⼀个消息有可能由⼀个或多个帧组成,FIN字段为1表⽰末尾帧。 RSV1~3:保留字段,只在扩展时使⽤,若未启⽤扩展则应置1,若收到不全为0的数据帧,且未协商扩展则⽴即终⽌连接 opcode: 标志当前数据帧的类型 ◦ 0x0: 表⽰这是个延续帧,当 opcode 为 0 表⽰本次数据传输采⽤了数据分⽚,当前收到的帧为其中⼀个分⽚ ◦ 0x1: 表⽰这是⽂本帧 ◦ 0x2: 表⽰这是⼆进制帧 ◦ 0x3-0x7: 保留,暂未使⽤ ◦ 0x8: 表⽰连接断开 ◦ 0x9: 表⽰ ping 帧 ◦ 0xa: 表⽰ pong 帧 ◦ 0xb-0xf: 保留,暂未使⽤ mask:表⽰Payload数据是否被编码,若为1则必有Mask-Key,⽤于解码Payload数据。仅客⼾端发送给服务端的消息需要设置。 Payload length:数据载荷的⻓度,单位是字节, 有可能为7位、7+16位、7+64位。假设Payload length = x ◦ x为0~126:数据的⻓度为x字节 ◦ x为126:后续2个字节代表⼀个16位的⽆符号整数,该⽆符号整数的值为数据的⻓度 ◦ x为127:后续8个字节代表⼀个64位的⽆符号整数(最⾼位为0),该⽆符号整数的值为数据的 ⻓度 Mask-Key:当mask为1时存在,⻓度为4字节,解码规则: DECODED[i] = ENCODED[i] ^ MASK[i % 4] Payload data: 报⽂携带的载荷数据

4.2websocketpp介绍

WebSocketpp是⼀个跨平台的开源(BSD许可证)头部专⽤C++库,它实现了RFC645(WebSocket协议)和RFC7692(WebSocketCompression Extensions)。它允许将WebSocket客⼾端和服务器功能集成到C++程序中。在最常⻅的配置中,全功能⽹络I/O由Asio⽹络库提供。 WebSocketpp同时⽀持HTTP和Websocket两种⽹络协议, ⽐较适⽤于我们本次的项⽬, 所以我们选⽤该库作为项⽬的依赖库⽤来搭建HTTP和WebSocket服务器。 该项目的相关网站如下: github:https://github.com/zaphoyd/websocketpp 用户手册:http://docs.websocketpp.org/ 官网:http://www.zaphoyd.com/websocketpp

4.2.1常用接口介绍

服务器类:

日志等级:

WebSocketPP库内置了自己的日志模块(无法替换,除非修改库内所有日志输出代码并重新编译安装)。这里我们主要关注其日志级别设置,通过禁用不必要的日志输出来避免运行时大量日志干扰核心信息查看。

连接对象:

http相关:

4.3搭建一个简单的http/websocket服务器

服务端:

makefile:

注意因为websocket是顺带实现http相关接口的,所以路由什么的工作都需要我们自己去完成。我们这里运行server之后搁网址里面在http:://你的服务器地址:9000之后加上无论什么他都会给你返回个hello world,因为这里我们是简单的实现了下,并没有作任何路由: 在这里插入图片描述 在这里插入图片描述 控制台输出如下:

如果我们想要看到websocket通信,可以使用下面的html代码进行,注意服务器地址改成你自己的:

服务端保持运行的情况下,用浏览器打开这段html会显示如下内容: 在这里插入图片描述 当我们提交内容后显示效果如下: 在这里插入图片描述

 

 

 

 



评论(已关闭)

评论已关闭

日历

2025 年 10 月
 123456
78910111213
14151617181920
21222324252627
282930