基于 C/S 架构的 IoT 设备管理平台,支持多用户通过 TCP 网络远程管理设备(增删改查/排序)。大创课程设计项目。
.
├── Makefile # 项目构建文件
├── README.md
├── build/ # 编译产物 (client / server)
├── client/
│ └── main.c # 客户端主程序
├── server/
│ └── main.c # 服务端主程序
├── src/
│ ├── device.c # 设备管理核心逻辑 (增删改查/排序/持久化)
│ ├── login.c # 登录/注册交互界面
│ ├── llist.c # 通用双向循环链表 (增删改查/排序/文件I/O)
│ ├── protocol.c # JSON 协议打包/解析
│ ├── queue.c # 线程安全请求/响应队列
│ └── session.c # 在线会话管理
├── include/
│ ├── device.h # 设备结构体与 API 声明
│ ├── llist.h # 链表通用库头文件
│ ├── login.h # 登录模块声明
│ ├── protocol.h # 协议命令、状态码、JSON Key 宏定义
│ ├── queue.h # 请求/响应队列 API
│ ├── session.h # 在线会话结构体与 API
│ └── user.h # 用户数据模块
└── data/ # 运行时数据文件 (自动生成)
├── user.dat # 用户数据
└── device.dat # 设备数据
- 注册 — 用户名 + 密码终端掩码输入
- 登录 — 验证成功后返回 Session ID (sid),后续操作凭证
- 登出 — 销毁会话,回收资源
| 操作 | 说明 |
|---|---|
| 添加设备 | 设备 ID 全局唯一(7位数字),自动绑定归属用户 |
| 删除设备 | 仅允许删除自己的设备 |
| 查询设备 | 按 ID / 名称 / 类型 / 状态 搜索自己的设备 |
| 修改设备 | 更新设备的名称/类型字段 |
| 设备列表 | 列出当前用户的所有设备 |
| 设备排序 | 按 ID 升序/降序排列 |
- JSON 文本协议 — 可读性好,方便调试
\n帧分隔 — 简单可靠的粘包切割- 状态码体系 — 统一错误码,客户端友好提示
| 命令 | 说明 | 需登录 |
|---|---|---|
REGISTER |
注册新用户 | 否 |
LOGIN |
登录 | 否 |
LOGOUT |
登出 | 是 |
DEV_ADD |
添加设备 | 是 |
DEV_DEL |
删除设备 | 是 |
DEV_QUERY |
查询设备 | 是 |
DEV_UPDATE |
修改设备 | 是 |
DEV_LIST |
列出全部设备 | 是 |
DEV_SORT |
设备排序 | 是 |
{"cmd":"CMD_NAME","sid":"session_id","params":{...}}{"code":1,"msg":"success","data":{...}}| 状态码 | 含义 |
|---|---|
1 |
成功 |
1001 |
用户名已存在 |
1002 |
账号或密码错误 |
1003 |
未登录,拒绝访问 |
2001 |
设备不存在 |
2002 |
参数缺失/格式错误 |
2003 |
会话 ID 失效 |
# 注册
→ {"cmd":"REGISTER","sid":"","params":{"username":"alice","password":"123456"}}
← {"code":1,"msg":"register success","data":{}}
# 登录
→ {"cmd":"LOGIN","sid":"","params":{"username":"alice","password":"123456"}}
← {"code":1,"msg":"login success","data":{"sid":"sid_alice_1712345678_42"}}
# 添加设备
→ {"cmd":"DEV_ADD","sid":"sid_alice_1712345678_42","params":{"id":"1000001","name":"温湿度传感器","type":"ESP32"}}
← {"code":1,"msg":"device added","data":{}}
# 查询设备列表
→ {"cmd":"DEV_LIST","sid":"sid_alice_1712345678_42","params":{}}
← {"code":1,"msg":"list success","data":[{"id":1000001,"name":"温湿度传感器","type":"ESP32",...}]}主线程 ── 事件循环,从请求队列取消息,串行执行业务逻辑
├── accept_thread (×1) accept() 监听新连接
├── client_recv_thread (×N) 每客户端一条,recv() + 粘包切割 + 入队
└── send_worker_thread (×1) 可靠发送,循环 send() 避免短写
详细设计见前文 服务器架构分析 及 IoT 平台对比讨论。
- OS: Linux / WSL / Windows (MinGW / Cygwin)
- 编译器: GCC (支持 C99)
- 依赖: cJSON (已内嵌于项目中)
- 链接库:
-lpthread
# 编译全部 (client + server)
make
# 仅编译客户端
make build/client
# 仅编译服务端
make build/server
# 清理
make clean
# 清理后重新编译
make rebuild编译产物输出到 build/ 目录。
# 1. 启动服务端 (端口号自定义)
./build/server 10045
# 2. 启动客户端 (IP + 端口)
./build/client 127.0.0.1 10045注意:请先创建
data/目录,或由程序在首次运行时自动生成。
设备数据和用户数据通过通用链表库 (llist) 进行二进制文件持久化:
- 文件格式:
数据条数(4B) + 单条长度(4B) + 数据块(N×size) - 启动时自动加载,每次写操作后自动保存
- 结构体变更时自动检测
size不匹配并重建(防止旧格式数据污染)
| 技术点 | 实现方案 |
|---|---|
| I/O 模型 | 每客户端一条接收线程 + 非阻塞 send |
| 线程同步 | pthread_mutex_t + pthread_cond_t 条件变量队列 |
| 粘包处理 | \n 分隔符 + 缓冲区拼接切割 |
| 数据持久化 | 自定义二进制格式 (num/size/payload) |
| 设备归属 | owner 字段 + 服务器端权限校验 |
| 会话管理 | sid (时间戳+随机数) + 全局链表 |
| 终端密码 | 关闭终端回显,* 掩码输出 |
| JSON | cJSON 库解析/构建 |
本项目仅用于教学和学习目的。