1. 本节课在整个项目中的位置
本项目是一个 预约系统 。
当前阶段还没有接数据库,本节课的重点是:
-
补全服务端通信框架
-
让客户端能够连接服务器
-
客户端把数据按 JSON 格式 发给服务器
-
服务器能够解析 JSON,并返回处理结果
也就是说,这节课完成的是:
"客户端 --- 服务器端 --- JSON 协议通信" 这条主线。
2. 本节课学了什么
这节课主要有两大部分:
第一部分:补全服务端通信框架
在上节课监听套接字 Lis_Socket 的基础上,这节课继续补全了:
-
LibEvent类 -
CallBack回调基类 -
Accept_CallBack -
Recv_CallBack
通过这些类,服务器就可以:
-
监听客户端连接
-
接收新连接
-
接收客户端发送的数据
-
给客户端回复消息
第二部分:引入 JSON 通信
客户端和服务器之间传输的数据,不再是随便写的字符串,而是改成了 JSON 格式。
你们这节课重点学习了:
-
JSON 是什么
-
C++ 里怎么使用
jsoncpp -
如何把数据组装成 JSON
-
如何把收到的 JSON 再解析回来
-
如何设计注册、登录等报文格式
3. JSON 这一节的核心知识
什么是 JSON
JSON 本质上是一种 纯字符串格式的数据 ,适合网络传输。
它的优点是:
-
格式统一
-
可读性好
-
方便扩展字段
-
各种语言都支持
它主要有两种结构:
-
对象 Object :
{},键值对 -
数组 Array :
[],有序集合
例如注册请求就可以写成:
{
"type": "ZC",
"user_tel": "13900000000",
"user_name": "xiaowang",
"user_passwd": "123456"
}
4. C++ 中使用 jsoncpp
这节课你们使用的是 jsoncpp 库。
主要接触了三个类:
Json::Value
最核心的类。
用来存放 JSON 数据,不管是字符串、数字、对象还是数组,最后都可以统一放到 Value 里。
例如:
Json::Value val;
val["type"] = "ZC";
val["user_tel"] = user_tel.c_str();
val["user_name"] = user_name.c_str();
val["user_passwd"] = user_passwd.c_str();
Json::FastWriter
作用:把 Value 转成紧凑的 JSON 字符串,适合网络传输。
Json::Reader
作用:把收到的 JSON 字符串解析成 Value 对象,方便程序读取字段。
例如:
Json::Reader reader;
reader.parse(buff, val);
5. 本节课的协议设计
这节课非常关键的一点,就是你们开始有"协议"的概念了。
也就是客户端发给服务器的数据,不是乱发,而是先约定格式。
你们的做法
用 type 字段区分不同请求类型,例如:
-
"ZC":注册 -
"DL":登录 -
后面还可以扩展
"CKYY":查看预约
这样服务器收到数据后,先看 type,再决定调用哪个处理函数。
注册协议
{
"type": "ZC",
"user_tel": "13900000000",
"user_name": "xiaowang",
"user_passwd": "123456"
}
登录协议
{
"type": "DL",
"user_name": "xiaowang",
"user_passwd": "123456"
}
返回协议
{
"status": "OK"
}
或者
{
"status": "ERR"
}
这说明你们已经开始从"随便收发数据"进入到"按协议收发数据"的阶段了,这一步非常重要。
6. 服务端代码这节课补全了什么
Lis_Socket
负责监听套接字,完成:
-
socket() -
bind() -
listen()
作用就是先把服务器的"门口"搭好。
LibEvent
负责事件管理,主要做三件事:
-
Init():初始化事件系统 -
Lib_Add(fd, callback):注册描述符和回调对象 -
Dispatch():启动事件循环
一句话理解:
Libevent 负责监听和调度,谁有事件就调用谁的回调函数。
CallBack
回调基类,统一规定接口:
virtual void CallBack_Fun() = 0;
作用是:
让不同类型的事件都用统一方式来处理,这体现了继承和多态。
Accept_CallBack
处理监听套接字上的事件。
当有客户端连接到来时:
-
调用
accept() -
生成新的连接套接字
-
再把新的连接套接字注册到事件系统里
一句话记:
负责接新客户端。
Recv_CallBack
处理连接套接字上的事件。
当客户端发送数据时:
-
调用
recv() -
收到客户端发来的 JSON
-
解析 JSON
-
打印字段
-
组装返回 JSON
-
再发回客户端
一句话记:
负责真正收发数据。
7. 客户端这节课做了什么
客户端这节课重点完成了:
-
连接服务器
-
显示菜单
-
输入注册信息
-
组装 JSON 请求
-
把 JSON 发给服务器
-
接收服务器返回的 JSON
-
解析
status -
输出"注册成功/失败"
例如 Zc_user() 做的就是这整套流程:
-
从键盘输入手机号、用户名、密码
-
组装成注册 JSON
-
send()发给服务器 -
recv()接服务器回包 -
用
Json::Reader解析 -
判断
status是否为"OK"
这说明客户端已经不只是"连上服务器",而是已经能按协议和服务器正常交互了。
8. 本节课完整流程
你复习时重点记这条主线:
-
服务器先创建监听套接字
-
初始化
LibEvent -
把监听套接字注册到事件系统
-
客户端连接服务器
-
服务器触发
Accept_CallBack,执行accept() -
得到新的连接套接字
-
再把新的连接套接字注册到事件系统
-
客户端输入注册信息
-
客户端把数据封装成 JSON 发给服务器
-
服务器触发
Recv_CallBack,执行recv() -
服务器解析 JSON,读取
type、user_tel、user_name、user_passwd -
服务器返回
{ "status": "OK" } -
客户端解析返回值并显示"注册成功"
9. 这节课最重要的知识点
第一,通信框架已经跑通
现在已经不是只有监听了,而是已经实现了:
-
客户端连接服务器
-
服务器接收数据
-
服务器回复数据
-
客户端解析回复
第二,开始有"协议设计"意识
你们不再是直接发字符串,而是开始设计:
-
请求报文格式
-
返回报文格式
-
业务类型字段
type
这一步是后面接数据库、做登录、预约、取消预约的基础。
第三,面向对象和事件驱动结合起来了
这节课不只是网络通信,还学了设计思想:
-
Lis_Socket:封装监听 socket -
LibEvent:封装事件系统 -
CallBack+ 子类:通过继承和多态分开处理不同事件
也就是说:
socket 负责通信,libevent 负责调度,回调类负责具体处理逻辑。
10. 本节课的结果
从截图和代码效果看,这节课已经实现了:
-
客户端成功连接服务器
-
客户端发送注册 JSON
-
服务器成功收到并解析 JSON
-
服务器打印出注册信息
-
服务器返回状态 JSON
-
客户端解析状态并显示"注册成功"
这说明你们预约系统第一阶段的通信骨架已经基本搭好了。后面数据库、登录校验、预约业务,都是在这个框架上继续往下做。
11. 一段适合记在本子上的阶段总结
这节课在上节课监听套接字封装的基础上,继续补全了服务端通信框架,引入了 LibEvent 类和回调类体系,通过 Accept_CallBack 处理新连接,通过 Recv_CallBack 处理数据接收。同时,客户端开始使用 jsoncpp 将注册信息封装为 JSON 发送给服务器,服务器解析后再返回状态 JSON。到这里,客户端与服务器端最基础的 JSON 通信已经跑通,为下一步接入数据库和实现登录、预约等业务功能打下了基础。
12. 最短背诵版
本节课主要完成了两件事:第一,补全基于 libevent 的服务端事件处理框架;第二,使用 jsoncpp 实现客户端和服务器之间的 JSON 协议通信,并完成注册请求与状态回复。
先说一下json如何安装,
json是什么 ,是一种纯
一、json介绍
JSON 是一种纯字符串形式的数据,它本身不提供任何方法(函数),非常适合在网络中进行传输。JavaScript、PHP、Java、Python、C++ 等编程语言中都内置了处理 JSON 数据的方法。
JSON 是基于 JavaScript (Standard ECMA-262 3rd Edition - December 1999) 的一个子集,是一种开放的、轻量级的数据交换格式,采用独立于编程语言的文本格式来存储和表示数据,易于程序员阅读与编写,同时也易于计算机解析和生成,通常用于在 Web 客户端(浏览器)与 Web 服务器端之间传递数据。
在 JSON 中,使用以下两种方式来表示数据:
- Object(对象):键 / 值对(名称 / 值)的集合,使用花括号
{ }定义。在每个键 / 值对中,以键开头,后跟一个冒号:,最后是值。多个键 / 值对之间使用逗号,分隔,例如{"name":"C语言中文网","url":"http://c.biancheng.net"}; - Array(数组):值的有序集合,使用方括号
[ ]定义,数组中每个值之间使用逗号,进行分隔。
一个简单的 JSON 数据:
bash
{
"Name": "C语言中文网",
"Url": "http://c.biancheng.net/",
"Tutorial": "JSON",
"Article": [
"JSON 是什么?",
"JSONP 是什么?",
"JSON 语法规则"
]
}
我们要操作上面JSON 数据需要那几个类,首先第一点 要生成上面的字符串,这个字符串就是我们网络传输的格式,对方收到后按照这个格式来解析,所以我们组装协议的时候也需要组装成这个样子。
c++ 使用 jsoncpp
使用 jsoncpp 库解析 json 格式的数据,需要三个类:
- Value 类:将 json 支持的数据类型(字符串、数字、数组、对象等)进行了包装,最终得到一个统一的 Value 类型,是 jsoncpp 中最核心的数据结构。
- FastWriter 类:将 Value 对象中的数据序列化为紧凑的无格式字符串,适合网络传输等场景。
- Reader 类:实现反序列化功能,将 json 格式的字符串解析并转换为 Value 类型对象,方便程序读取和操作。
Value 类成员方法
cpp
string toStyledString() const;
- 作用:将 Value 对象序列化为带缩进、换行的格式化字符串,可读性强,适合写入配置文件。
- 特点:输出格式美观,便于人工阅读,但数据体积相对较大。
FastWriter 类成员方法
cpp
string Json::FastWriter::write(const Value& root);
- 作用:将 Value 对象序列化为紧凑单行字符串,无任何冗余格式。可用于网络传输。
- 特点:数据体积小、传输效率高,是网络通信场景的首选序列化方式。
Reader 类成员方法

协议设计:我们约定1代表注册 2代表登录,如果通过json来传递的话 ,可以在json中传递一个报文
1 Type:"ZC" "DL" "CKYY(查看预约)"
给对方发数据时 看类型即可
json格式的报文设计如下:
注册:
cpp
{
"type": "ZC",
"user_tel": "13900000000",
"user_name": "xiaowang",
"user_passwd": "123456"
}
登录:
cpp
{
"type": "DL",
"user_name": "xiaowang",
"user_passwd": "123456"
}
第一个字段就是报文的类型 ,根据类型调具体处理类型的函数。
注册及登录返回信息
cpp
{
"status": "OK",
"status": "ERR"
}
