
🎬 个人主页 :艾莉丝努力练剑
❄专栏传送门 :《C语言》《数据结构与算法》《C/C++干货分享&学习过程记录》
《Linux操作系统编程详解》《笔试/面试常见算法:从基础到进阶》《Python干货分享》
⭐️为天地立心,为生民立命,为往圣继绝学,为万世开太平
🎬 艾莉丝的简介:

文章目录
- [1 ~> ChatServer HTTP 接口模块实现](#1 ~> ChatServer HTTP 接口模块实现)
-
- [1.1 整体类结构设计](#1.1 整体类结构设计)
-
- [1.1.1 ChatServer 类声明](#1.1.1 ChatServer 类声明)
- [1.1.2 依赖头文件](#1.1.2 依赖头文件)
- [1.1.3 通用响应工具函数实现](#1.1.3 通用响应工具函数实现)
- [1.2 接口 1:创建会话接口](#1.2 接口 1:创建会话接口)
-
- [1.2.1 接口规约](#1.2.1 接口规约)
- [1.2.2 业务流程](#1.2.2 业务流程)
- [1.2.3 完整实现代码](#1.2.3 完整实现代码)
- [1.3 接口 2:获取会话列表接口](#1.3 接口 2:获取会话列表接口)
-
- [1.3.1 接口规约](#1.3.1 接口规约)
- [1.3.2 业务流程](#1.3.2 业务流程)
- [1.3.3 完整实现代码](#1.3.3 完整实现代码)
- [1.4 接口 3:获取可用模型列表接口](#1.4 接口 3:获取可用模型列表接口)
-
- [1.4.1 接口规约](#1.4.1 接口规约)
- [1.4.2 业务流程](#1.4.2 业务流程)
- [1.4.3 完整实现代码](#1.4.3 完整实现代码)
- [1.5 接口 4:删除会话接口](#1.5 接口 4:删除会话接口)
-
- [1.5.1 接口规约](#1.5.1 接口规约)
- [1.5.2 业务流程](#1.5.2 业务流程)
- [1.5.3 完整实现代码](#1.5.3 完整实现代码)
- [1.6 接口 5:获取会话历史消息接口](#1.6 接口 5:获取会话历史消息接口)
-
- [1.6.1 接口规约](#1.6.1 接口规约)
- [1.6.2 业务流程](#1.6.2 业务流程)
- [1.6.3 完整实现代码](#1.6.3 完整实现代码)
- [1.7 接口 6:发送消息 - 全量返回接口](#1.7 接口 6:发送消息 - 全量返回接口)
-
- [1.7.1 接口规约](#1.7.1 接口规约)
- [1.7.2 业务流程](#1.7.2 业务流程)
- [1.7.3 完整实现代码](#1.7.3 完整实现代码)
- [2 ~> SSE 流式增量返回接口(核心难点)](#2 ~> SSE 流式增量返回接口(核心难点))
-
- [2.1 接口 7:发送消息‑流式增量返回](#2.1 接口 7:发送消息‑流式增量返回)
-
- [2.1.1 接口规约](#2.1.1 接口规约)
- [2.1.2 httplib 关键 API:`set_chunked_content_provider`](#2.1.2 httplib 关键 API:
set_chunked_content_provider) - [2.1.3 HTTP 响应头设置(SSE 长连接)](#2.1.3 HTTP 响应头设置(SSE 长连接))
- [2.1.4 SDK 流式回调](#2.1.4 SDK 流式回调)
- [2.1.5 特殊处理点](#2.1.5 特殊处理点)
- [2.1.6 完整实现代码](#2.1.6 完整实现代码)
- [3 ~> 状态码业务语义总结](#3 ~> 状态码业务语义总结)
- [4 ~> 架构关键点总结](#4 ~> 架构关键点总结)
-
- [4.1 代码复用设计](#4.1 代码复用设计)
- [4.2 参数获取区分](#4.2 参数获取区分)
- [4.3 SSE 流式传输核心要点](#4.3 SSE 流式传输核心要点)
- [4.4 与 ChatSDK 的职责边界](#4.4 与 ChatSDK 的职责边界)
- [4.5 常见易错点](#4.5 常见易错点)
- 结尾

1 ~> ChatServer HTTP 接口模块实现
基于 httplib + jsoncpp 实现 AI 聊天服务后端接口,提供会话 CRUD、消息全量 / 流式增量返回能力。
1.1 整体类结构设计
1.1.1 ChatServer 类声明
cpp
// ChatServer.h
#pragma once
#include <memory>
#include <shared_ptr>
#include "ai_chat_sdk/ChatSk.h"
#include "httplib.h"
// 服务器配置结构体
struct ServerConfig{
std::string chatPTAPIKey;
std::string ollamaModelName;
std::string ollamaModelDesc;
std::string ollamaEndpoint;
};
class ChatServer
{
public:
ChatServer(const ServerConfig& config);
~ChatServer();
bool start(); // 启动http服务器
void stop(); // 停止服务器
bool isRunning() const;
private:
// 通用响应构造工具,消除重复JSON序列化代码
std::string buildResponse(const std::string& message, bool success = false);
// 接口处理私有回调方法
void handleCreateSessionRequest(const httplib::Request& request, httplib::Response& response);
void handleGetSessionListsRequest(const httplib::Request& request, httplib::Response& response);
void handleGetModelListsRequest(const httplib::Request& request, httplib::Response& response);
void handleDeleteSessionRequest(const httplib::Request& request, httplib::Response& response);
void handleGetHistoryMessagesRequest(const httplib::Request& request, httplib::Response& response);
void handleSendMessageRequest(const httplib::Request& request, httplib::Response& response);
void handleSendMessageStreamRequest(const httplib::Request& request, httplib::Response& response);
private:
ServerConfig _config;
std::unique_ptr<httplib::Server> _chatServer = nullptr;
std::shared_ptr<ai_chat_sdk::ChatSk> _chatSK = nullptr;
std::atomic<bool> _isRunning{false};
};
1.1.2 依赖头文件
cpp
// ChatServer.cpp
#include "ChatServer.h"
#include <ai_chat_sdk/util/myLog.h>
#include <jsoncpp/json/forwards.h>
#include <jsoncpp/json/value.h>
#include <jsoncpp/json/reader.h>
#include <jsoncpp/json/writer.h>
1.1.3 通用响应工具函数实现
- 作用:统一封装 JSON 序列化逻辑,消除各个接口内错误响应的重复代码
cpp
// ChatServer.cpp
namespace ai_chat_server
{
std::string ChatServer::buildResponse(const std::string& message, bool success)
{
Json::Value responseJson;
responseJson["success"] = success;
responseJson["message"] = message;
Json::StreamWriterBuilder writerBuilder;
return Json::writeString(writerBuilder, responseJson);
}
}
1.2 接口 1:创建会话接口
1.2.1 接口规约
- 请求 URL:
POST /api/session - 请求体 JSON:
{"model":"string"} - HTTP 状态码
- 200:创建成功
- 400:请求 JSON 格式错误 /model 参数缺失
- 500:SDK 内部创建会话失败
- 返回响应 JSON
json
{
"success": true,
"message": "create session success",
"data": {
"session_id": "string",
"model": "string"
}
}
1.2.2 业务流程
- 获取 POST 请求 body,使用 Json::Reader 反序列化
- 反序列化失败:返回 400,调用 buildResponse 生成错误 JSON
- 解析 model 字段,设置默认值
deepseek‑chat - 调用 SDK
_chatSK->createSession(modelName)生成 sessionId - sessionId 为空:返回 500 服务器内部错误
- 组装成功响应 JSON,序列化返回,状态码 200
1.2.3 完整实现代码
cpp
void ChatServer::handleCreateSessionRequest(const httplib::Request& request, httplib::Response& response)
{
Json::Value requestJson;
Json::Reader reader;
// 反序列化请求体
if(!reader.parse(request.body, requestJson))
{
std::string errStr = buildResponse("parse request body failed,json format error");
response.status = 400;
response.set_content(errStr, "application/json");
return;
}
// 解析model参数,设置默认模型
std::string modelName = requestJson.get("model", "deepseek-chat").asString();
// SDK创建会话
std::string sessionID = _chatSK->createSession(modelName);
if(sessionID.empty())
{
std::string errStr = buildResponse("create session failed");
response.status = 500;
response.set_content(errStr, "application/json");
return;
}
// 组装成功响应
Json::Value dataJson;
dataJson["session_id"] = sessionID;
dataJson["model"] = modelName;
Json::Value responseJson;
responseJson["success"] = true;
responseJson["message"] = "create session success";
responseJson["data"] = dataJson;
Json::StreamWriterBuilder writerBuilder;
std::string respStr = Json::writeString(writerBuilder, responseJson);
response.status = 200;
response.set_content(respStr, "application/json");
}
1.3 接口 2:获取会话列表接口
1.3.1 接口规约
- 请求 URL:
GET /api/sessions - 无请求 Body
- 返回 200,data 为会话对象数组
cpp
{
"success": true,
"message": "get session lists success",
"data": [
{
"id": "string",
"model": "string",
"created_at": 1700000000,
"updated_at": 1700000100,
"message_count": 2,
"first_user_message": "第一条用户提问内容"
}
]
}
1.3.2 业务流程
- 调用 SDK 获取全部 sessionId 列表
_chatSK->getSessionLists() - 创建 Json 数组对象
Json::Value dataArray(Json::arrayValue) - 遍历 sessionId 列表:
- 通过 sessionId 获取
std::shared_ptr<Session>会话对象 - 会话非空,填充 id、model、时间戳、消息计数、第一条用户消息
- 时间戳使用
static_cast<int64_t>做类型强转 session->_messages.front()获取第一条消息- 将会话 JSON 对象 append 进数组
- 通过 sessionId 获取
- 组装顶层响应 JSON,序列化返回 200
1.3.3 完整实现代码
cpp
void ChatServer::handleGetSessionListsRequest(const httplib::Request& request, httplib::Response& response)
{
std::vector<std::string> sessionIDs = _chatSK->getSessionLists();
Json::Value dataArray(Json::arrayValue);
for(const auto& sessionID : sessionIDs)
{
auto session = _chatSK->getSession(sessionID);
if(!session) continue;
Json::Value sessionJson;
sessionJson["id"] = session->_sessionId;
sessionJson["model"] = session->_modelName;
sessionJson["created_at"] = static_cast<int64_t>(session->_createdAt);
sessionJson["updated_at"] = static_cast<int64_t>(session->_updatedAt);
sessionJson["message_count"] = static_cast<int>(session->_messages.size());
if(!session->_messages.empty())
{
sessionJson["first_user_message"] = session->_messages.front()._content;
}
dataArray.append(sessionJson);
}
Json::Value responseJson;
responseJson["success"] = true;
responseJson["message"] = "get session lists success";
responseJson["data"] = dataArray;
Json::StreamWriterBuilder writerBuilder;
std::string respStr = Json::writeString(writerBuilder, responseJson);
response.status = 200;
response.set_content(respStr, "application/json");
}
1.4 接口 3:获取可用模型列表接口
1.4.1 接口规约
- 请求 URL:
GET /api/models - 无请求 Body
- 返回 200,data 为模型信息数组
json
{
"success": true,
"message": "get model lists success",
"data": [
{
"name": "deepseek‑chat",
"desc": "模型描述文本"
}
]
}
1.4.2 业务流程
- SDK 获取可用模型列表
_chatSK->getAvailableModels() - 循环填充每个模型
name、desc字段,存入 JSON 数组 - 组装顶层响应,序列化返回 200
1.4.3 完整实现代码
cpp
void ChatServer::handleGetModelListsRequest(const httplib::Request& request, httplib::Response& response)
{
auto modelLists = _chatSK->getAvailableModels();
Json::Value dataArray(Json::arrayValue);
for(const auto& modelInfo : modelLists)
{
Json::Value modelJson;
modelJson["name"] = modelInfo.modelName;
modelJson["desc"] = modelInfo._modelDesc;
dataArray.append(modelJson);
}
Json::Value responseJson;
responseJson["success"] = true;
responseJson["message"] = "get model lists success";
responseJson["data"] = dataArray;
Json::StreamWriterBuilder writerBuilder;
std::string respStr = Json::writeString(writerBuilder, responseJson);
response.status = 200;
response.set_content(respStr, "application/json");
}
1.5 接口 4:删除会话接口
1.5.1 接口规约
- 请求 URL:
DELETE /api/session/{session_id} - session_id 属于路径参数 ,通过
request.matches[1]捕获正则匹配分组 - HTTP 状态码
- 200:删除成功
- 404:会话不存在,删除失败
- 返回 JSON
json
{
"success": true,
"message": "delete session success"
}
1.5.2 业务流程
- 从路径匹配结果取出 sessionId
- 调用 SDK
_chatSK->deleteSession(sessionId) - 返回 true:200 成功;返回 false:404 会话不存在
- 使用 buildResponse 构造返回 JSON
1.5.3 完整实现代码
cpp
void ChatServer::handleDeleteSessionRequest(const httplib::Request& request, httplib::Response& response)
{
std::string sessionId = request.matches[1];
bool ret = _chatSK->deleteSession(sessionId);
if(ret)
{
std::string respStr = buildResponse("delete session success", true);
response.status = 200;
response.set_content(respStr, "application/json");
}
else
{
std::string respStr = buildResponse("delete session failed,session not found");
response.status = 404;
response.set_content(respStr, "application/json");
}
}
1.6 接口 5:获取会话历史消息接口
1.6.1 接口规约
- 请求 URL:
GET /api/session/{session_id}/history - session_id 路径参数,
request.matches[1]获取 - 状态码:200 成功;404 会话不存在
json
{
"success": true,
"message": "get history messages success",
"data": [
{
"id": "消息id",
"role": "user/assistant",
"content": "消息正文",
"timestamp": 1700000000
}
]
}
1.6.2 业务流程
- 获取路径 sessionId,获取会话 shared_ptr
- 会话为空返回 404
- 遍历会话
_messages成员,填充消息 id、role、content、时间戳,存入 JSON 数组 - 组装响应返回 200
1.6.3 完整实现代码
cpp
void ChatServer::handleGetHistoryMessagesRequest(const httplib::Request& request, httplib::Response& response)
{
std::string sessionId = request.matches[1];
auto session = _chatSK->getSession(sessionId);
if(!session)
{
std::string errStr = buildResponse("session not found");
response.status = 404;
response.set_content(errStr, "application/json");
return;
}
Json::Value dataArray(Json::arrayValue);
for(const auto& message : session->_messages)
{
Json::Value messageJson;
messageJson["id"] = message._messageId;
messageJson["role"] = message._role;
messageJson["content"] = message._content;
messageJson["timestamp"] = static_cast<int64_t>(message._timestamp);
dataArray.append(messageJson);
}
Json::Value responseJson;
responseJson["success"] = true;
responseJson["message"] = "get history messages success";
responseJson["data"] = dataArray;
Json::StreamWriterBuilder writerBuilder;
std::string respStr = Json::writeString(writerBuilder, responseJson);
response.status = 200;
response.set_content(respStr, "application/json");
}
1.7 接口 6:发送消息 - 全量返回接口
1.7.1 接口规约
实际前端业务优先使用流式增量接口;全量接口一次性等待模型完整结果返回
- 请求 URL:
POST /api/message - 请求体
json
{
"session_id": "string",
"message": "用户提问文本"
}
- 状态码:200 成功;400 参数解析失败;500AI 调用失败
- 返回响应
json
{
"success": true,
"message": "send message success",
"data": {
"session_id": "string",
"response": "模型完整回答文本"
}
}
1.7.2 业务流程
- 反序列化 POST 请求 body,失败返回 400
- 解析
session_id、message,任一为空返回 400 - SDK 调用
_chatSK->sendMessage(sessionId, message)获取完整回答 - 返回字符串为空代表 AI 调用失败,返回 500
- 组装 data 对象,序列化返回 200
1.7.3 完整实现代码
cpp
void ChatServer::handleSendMessageRequest(const httplib::Request& request, httplib::Response& response)
{
Json::Value requestJson;
Json::Reader reader;
if(!reader.parse(request.body, requestJson))
{
std::string errStr = buildResponse("parse request body failed,json format error");
response.status = 400;
response.set_content(errStr, "application/json");
return;
}
std::string sessionId = requestJson["session_id"].asString();
std::string message = requestJson["message"].asString();
if(sessionId.empty() || message.empty())
{
std::string errStr = buildResponse("session_id or message is empty");
response.status = 400;
response.set_content(errStr, "application/json");
return;
}
std::string assistantMessage = _chatSK->sendMessage(sessionId, message);
if(assistantMessage.empty())
{
std::string errStr = buildResponse("Faild to send AI response message");
response.status = 500;
response.set_content(errStr, "application/json");
return;
}
Json::Value dataJson;
dataJson["session_id"] = sessionId;
dataJson["response"] = assistantMessage;
Json::Value responseJson;
responseJson["success"] = true;
responseJson["message"] = "send message success";
responseJson["data"] = dataJson;
Json::StreamWriterBuilder writerBuilder;
std::string respStr = Json::writeString(writerBuilder, responseJson);
response.status = 200;
response.set_content(respStr, "application/json");
}
2 ~> SSE 流式增量返回接口(核心难点)
2.1 接口 7:发送消息‑流式增量返回
2.1.1 接口规约
- 请求 URL:
POST /api/message/async - 请求体 JSON:
{"session_id":"xxx","message":"用户问题"} - 返回:HTTP 200,SSE chunked 分块传输,响应格式
cpp
data:"片段1"
data:"片段2"
data:[DONE]
SSE 协议规范:每条事件行以
data:开头,两条换行\n\n作为事件结束分隔;最后发送data:[DONE]标记流式传输结束。
2.1.2 httplib 关键 API:set_chunked_content_provider
cpp
void Response::set_chunked_content_provider(
const std::string &content_type,
ContentProviderWithoutLength provider,
ContentProviderResourceReleaser resource_releaser = nullptr
);
content_type:响应 MIME 类型,SSE 一般使用text/event‑streamprovider回调签名:bool(size_t offset, httplib::DataSink &sink)- offset:当前数据偏移量
- DataSink:网络写入对象,调用
sink.write(buf,len)向客户端发送字节流;sink.done()结束流 - 返回
true:还有后续数据;返回false终止流
resource_releaser:资源释放回调,可选参数
2.1.3 HTTP 响应头设置(SSE 长连接)
Cache‑Control: no‑cache:禁用缓存,实时推送Connection: keep‑alive:保持长连接,持续推送分片数据
2.1.4 SDK 流式回调
_chatSK->sendMessageStream(sessionId, message, callback)
- callback 参数:
const std::string& chunk, bool last- chunk:模型返回增量文本片段
- last:
true代表全部流式数据接收完毕
2.1.5 特殊处理点
- 使用
Json::valueToQuotedString对 chunk 转义,防止文本内换行、引号破坏 SSE 协议格式 - 提前发送空块,避免客户端长时间无数据阻塞等待
- last=true 时,发送
data:[DONE]\n\n,调用sink.done()结束流
2.1.6 完整实现代码
cpp
void ChatServer::handleSendMessageStreamRequest(const httplib::Request& request, httplib::Response& response)
{
// 1.解析请求JSON
Json::Value requestJson;
Json::Reader reader;
if(!reader.parse(request.body, requestJson))
{
std::string errStr = buildResponse("parse request body failed,json format error");
response.status = 400;
response.set_content(errStr, "application/json");
return;
}
std::string sessionId = requestJson["session_id"].asString();
std::string message = requestJson["message"].asString();
if(sessionId.empty() || message.empty())
{
std::string errStr = buildResponse("session_id or message is empty");
response.status = 400;
response.set_content(errStr, "application/json");
return;
}
// 2.配置SSE流式响应头
response.status = 200;
response.set_header("Cache‑Control", "no‑cache");
response.set_header("Connection", "keep‑alive");
// 3.注册分块内容提供者
response.set_chunked_content_provider("text/event‑stream",
[this, sessionId, message](size_t /*offset*/, httplib::DataSink& datasink) -> bool
{
// SDK的流式回调,收到模型分片就执行
auto writeChunk = [&datasink](const std::string& chunk, bool last)
{
// 将chunk转义为json字符串,防止特殊字符破坏SSE协议
std::string quotedChunk = Json::valueToQuotedString(chunk.c_str());
std::string sseFrame = "data:" + quotedChunk + "\n\n";
datasink.write(sseFrame.c_str(), sseFrame.size());
if(last)
{
// 流式结束标记
std::string doneFrame = "data:[DONE]\n\n";
datasink.write(doneFrame.c_str(), doneFrame.size());
datasink.done();
}
};
// 先发空块,避免客户端长时间等待
writeChunk("", false);
// 调用SDK发起流式对话,writeChunk作为分片回调
_chatSK->sendMessageStream(sessionId, message, writeChunk);
return true; // true表示后续还有数据
}
);
}
3 ~> 状态码业务语义总结
| HTTP 状态码 | 业务含义 |
|---|---|
| 200 | 请求业务处理成功 |
| 400 | 客户端参数错误:JSON 解析失败、字段缺失 / 为空 |
| 404 | 会话 ID 不存在(删除会话、获取历史消息) |
| 500 | 服务端内部业务错误:创建会话失败、AI 模型调用失败 |
4 ~> 架构关键点总结
4.1 代码复用设计
- 提取
buildResponse工具函数,统一构造 success/message 格式 JSON,消除各个接口重复序列化代码。 - 所有私有接口处理函数不会被外部直接调用,声明在 class private 域。
4.2 参数获取区分
- 请求体参数(POST) :
request.body,需要 Json::Reader 反序列化;创建会话、发送消息接口使用。 - 路径参数(DELETE/GET 路径携带 id) :
request.matches[1]正则捕获分组;删除会话、获取历史消息接口使用。
4.3 SSE 流式传输核心要点
- 采用 HTTP 分块传输 (chunked),
Content‑Length响应头不存在,数据分片实时推送。 - DataSink 负责向 socket 写入字节流,
write()立刻发送网络报文,不等待缓冲区满。 - 回调分层:
httplib的 provider 回调中再嵌套 SDK 的 chunk 回调;SDK 收到模型分片,触发内层 writeChunk,组装 SSE 帧,调用 datasink 写网络。 - 必须对输出文本做 JSON 转义,否则文本中的
"、\n会破坏 SSE 协议帧格式。
4.4 与 ChatSDK 的职责边界
- ChatServer:HTTP 协议层,解析 http 请求、组装 http 响应、参数校验,协议格式转换。
- ChatSDK:业务逻辑层,会话管理、调用大模型 API,提供同步 sendMessage、异步流式 sendMessageStream。
4.5 常见易错点
- 类成员函数实现忘记写
ChatServer::作用域限定符,编译器识别为全局函数。 - jsoncpp 反序列化忘记引入
reader.h头文件。 - SSE 帧格式错误:少写换行
\n\n,导致前端无法解析事件。 - 时间戳没有做
static_cast<int64_t>类型转换,JSON 输出数值类型异常。 - 流式回调返回 false,会直接中断后续分片接收。
- 路径参数 matches 下标写错,拿不到 session_id。
结尾
uu们,本文的内容到这里就全部结束了,艾莉丝在这里再次感谢您的阅读!
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| ### 艾莉丝努力练剑 C/C++ & Linux 底层探索者 | 一个正在努力练剑的技术博主 *** ** * ** *** 👀 【关注】 跟随我一起深耕技术领域,见证每一次成长。 ❤️ 【点赞】 让优质内容被更多人看见,让知识传递更有力量。 ⭐ 【收藏】 把核心知识点存好,在需要时随时查、随时用。 💬 【评论】 分享你的经验或疑问,评论区一起交流避坑! 不要忘记给博主"一键四连"哦! "今日练剑达成!"
"技术之路难免有困惑,但同行的人会让前进更有方向。" |
结语:希望对学习Linux相关内容的uu有所帮助,不要忘记给博主"一键四连"哦!
往期回顾:
【AI大模型接入SDK】ChatServer 启动与停止模块实现
🗡博主在这里放了一只小狗,大家看完了摸摸小狗放松一下吧!🗡 ૮₍ ˶ ˊ ᴥ ˋ˶₎ა
