跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表
C++

C++ 实现 JSON 与 HTTP 协议:从零构建 Web 计算器服务器

综述由AI生成C++ 环境下 JSON 数据的序列化与反序列化实践,重点讲解了 nlohmann/json 库的使用方法及底层原理。在此基础上,深入剖析了 HTTP 协议的结构,包括请求行、请求头、响应报文及常见状态码。最后通过实战案例,从零构建了一个支持静态资源访问和动态计算的 Web 服务器,涵盖了 Socket 封装、线程池调度、TCP 报文解析及业务逻辑路由等关键技术点。

PgDevote发布于 2026/3/23更新于 2026/5/24 浏览
C++ 实现 JSON 与 HTTP 协议:从零构建 Web 计算器服务器

C++ 实现 JSON 与 HTTP 协议:从零构建 Web 计算器服务器

在之前的网络编程实践中,我们处理过 TCP 字节流传输。对于面向字节流的 TCP 协议,通信双方通常需要定义一种结构化的数据来描述传输内容。直接传递内存中的结构体字节会引发字节序和内存对齐的问题,不同平台和编译器的规则可能不一致。因此,我们需要借助序列化技术,将结构化数据转换为连续的字节流。

文本序列化(如 JSON)直观、可读性高,便于调试;而二进制序列化(如 Protobuf)体积更小、解析更快。在实际开发中,我们通常使用成熟的第三方库来完成这项工作。本文将介绍如何使用 C++ 结合 nlohmann/json 库处理 JSON 数据,并基于 HTTP 协议实现一个简易的 Web 服务器。

JSON 数据处理

JSON(JavaScript Object Notation)是一种轻量级、基于文本的数据交换格式。它源于 JavaScript,但已广泛应用于多种编程语言。JSON 本质上是一种符合特定规范的字符串,支持整型、浮点型、布尔型、字符串、对象和数组等类型。

在 C++ 中,常用的 JSON 库是 nlohmann/json(即 json.hpp)。它是一个头文件库,无需编译安装,只需将其包含在项目目录中即可。该库提供了一个 json 类对象,用于存储和操作 JSON 数据。

初始化与操作

创建 json 对象主要有两种方式。第一种是通过构造函数进行列表初始化,利用 C++11 特性传入键值对或元素列表:

#include <nlohmann/json.hpp>
using json = nlohmann::json;

// 对象初始化
json j = {{"name", "WZ"}, {"age", 20}, {"gender", "girl"}};

// 数组初始化
json arr = {1, 2, 3, 4, 5};

更推荐的方式是使用赋值运算符,这更符合 C++ 标准库容器的使用习惯:

json j;
j["name"] = "wz";
j["age"] = 20;
j["gender"] = "girl";

序列化与反序列化

json 类提供了 dump() 成员函数用于序列化,返回类型为 std::string。若不传参数,默认生成紧凑格式;若传入整数参数,则按指定缩进格式化输出。

std::string s = j.dump(); // 紧凑格式
std::string s_pretty = j.dump(2); // 2 格缩进

反序列化使用静态成员函数 parse(),接收 JSON 格式的字符串并还原为 json 对象。为了简化字符串中转义字符的处理,C++11 引入了原始字符串字面量语法 R"()":

std::string raw_json = R"({"name":"WZ","age":18})";
json j = json::parse(raw_json);

底层原理简述

nlohmann/json 内部维护一个联合体来存储不同类型的数据,通过类型标签区分当前对象是对象、数组还是基本类型。operator[] 重载了字符串和整型访问,自动处理类型转换和容器初始化。这种设计使得 API 既灵活又直观,同时保证了类型安全。

HTTP 协议基础

HTTP 是基于 TCP 的应用层协议,定义了客户端与服务器之间的交互规则。理解其报文结构是实现 Web 服务器的关键。

URL 与域名解析

URL(统一资源定位符)由协议、域名、端口、路径、查询参数等组成。浏览器输入网址后,首先进行域名解析(DNS),将域名转换为 IP 地址,才能建立 TCP 连接。域名解析过程涉及本地缓存、Hosts 文件以及 DNS 服务器的迭代查询。

请求与响应报文

HTTP 请求报文由请求行、请求头、空行和可选的请求正文组成。请求行包含方法(GET/POST 等)、URL 和协议版本。

常见的请求方法包括 GET(获取资源)和 POST(提交数据)。GET 请求通常不带正文,数据放在 URL 查询参数中;POST 请求则携带正文,常用于表单提交或文件上传。

响应报文结构与请求类似,由响应行、响应头、空行和响应正文组成。状态码指示请求结果,如 200 OK、404 Not Found、500 Internal Server Error 等。

Web 服务器实现

基于上述理论,我们可以用 C++ 编写一个简单的 Web 服务器。整体架构遵循经典的 Socket 编程模式:创建监听套接字、绑定端口、接受连接、处理请求。

核心组件设计

为了代码清晰,我们将 Socket 操作封装在一个 sock 类中,采用 RAII 思想管理资源生命周期。主服务器类 Httpserver 负责启动监听和线程池调度。

class sock {
public:
    int socketfd = -1;
    ~sock() { if (socketfd >= 0) ::close(socketfd); }
    void socket() { /* ... */ }
    void bind(std::string ip, uint16_t port) { /* ... */ }
    void listen() { /* ... */ }
    int accept(struct sockaddr_in* client, socklen_t* len) { /* ... */ }
private:
    // ... 省略部分实现细节
};

线程池与任务处理

服务端需要并发处理多个客户端连接。为了避免频繁创建销毁线程的开销,引入线程池机制。主线程负责 accept 新连接,将连接句柄封装为 Task 任务放入队列,工作线程从队列获取任务执行具体的 HTTP 逻辑。

请求解析与路由

读取客户端数据时,需依据 HTTP 协议格式判断是否收到完整报文。请求头结束标志为连续的两个回车换行符 \r\n\r\n。对于 POST 请求,还需根据 Content-Length 头读取完整的请求正文。

解析完成后,根据请求方法分发处理逻辑:

  • GET 请求:映射到文件系统,读取静态资源(HTML、图片等),设置对应的 MIME 类型。
  • POST 请求:解析请求体中的键值对,执行业务逻辑(如本例中的计算器功能)。
void run() {
    Http_Request hr;
    bool get_result = Get_HttpRequest(socketfd, hr);
    if (!get_result) return;

    std::string res;
    if (hr.method == "GET") {
        res = Http_Get_Handler(hr);
    } else if (hr.method == "POST") {
        res = Http_Post_Handler(hr);
    } else {
        // 不支持的方法
        close(socketfd);
        return;
    }

    send(socketfd, res.c_str(), res.size(), 0);
    close(socketfd);
}

业务逻辑示例:计算器

在 POST 处理器中,我们解析表单数据(如 a=10&op=+&b=20),执行计算并将结果以 HTML 形式返回。注意处理除零错误及非法运算符的情况。

bool process_calculation(std::unordered_map<std::string, std::string>& val, int& result) {
    int a = std::stoi(val["a"]);
    int b = std::stoi(val["b"]);
    std::string op = val["op"];
    // 处理 URL 编码的运算符
    if (op == "%2B") op = "+"; // ...
    switch (op[0]) {
        case '+': result = a + b; break;
        case '-': result = a - b; break;
        case '*': result = a * b; break;
        case '/':
            if (b == 0) return false;
            result = a / b; break;
    }
    return true;
}

静态资源服务

GET 请求主要处理静态文件。通过 URL 路径拼接服务器根目录,查找文件是否存在。若存在,读取文件内容并构建 200 OK 响应;若不存在,返回 404 错误页面。文件扩展名用于确定 Content-Type,确保浏览器正确渲染。

总结

本文详细讲解了如何在 C++ 中使用 JSON 库处理数据交换,并基于 HTTP 协议实现了基础的 Web 服务器。通过封装 Socket 操作、引入线程池以及设计合理的请求路由机制,我们构建了一个具备静态资源服务和动态计算能力的服务器原型。掌握这些底层原理,有助于深入理解网络编程的核心逻辑,为后续学习 HTTPS、异步 IO 等高级主题打下坚实基础。

目录

  1. C++ 实现 JSON 与 HTTP 协议:从零构建 Web 计算器服务器
  2. JSON 数据处理
  3. 初始化与操作
  4. 序列化与反序列化
  5. 底层原理简述
  6. HTTP 协议基础
  7. URL 与域名解析
  8. 请求与响应报文
  9. Web 服务器实现
  10. 核心组件设计
  11. 线程池与任务处理
  12. 请求解析与路由
  13. 业务逻辑示例:计算器
  14. 静态资源服务
  15. 总结
  • 💰 8折买阿里云服务器限时8折了解详情
  • GPT-5.5 超高智商模型1元抵1刀ChatGPT中转购买
  • 代充Chatgpt Plus/pro 帐号了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • MCP Server 实现 Excel 表格一键生成可视化图表 HTML 报告
  • Qclaw 微信 AI 智能体使用教程
  • C++ 笔试算法实战:打怪模拟、字符串分类与连通分量
  • C++ 多态深度解析:从虚函数表到底层机制
  • Java 零基础入门教程:环境搭建、核心语法与实战
  • Pico 无线串流 SteamVR 安装与网络环境配置指南
  • TS2320 错误的本质、触发场景与在 Angular / RxJS 项目中的系统化应对
  • Stable Diffusion 训练实战:损失函数调优指南
  • JavaScript 简介:从网页脚本到全栈语言
  • SkyWalking .NET / C++ / Lua 探针现状与社区支持
  • 论文 AI 率多少算正常?各高校 AIGC 检测标准汇总
  • OpenClaw 安装部署全流程 - 搭建自托管 AI 助手
  • Linux 编译器 gcc/g++与动态静态库详解
  • 基于魔搭与 LLaMA Factory 的大模型微调全流程实操
  • 前端代码分割与懒加载实践
  • AI 扩展定律背后的神话与真相
  • 前端响应式进阶:从 vw/vh 到 clamp() 的实战思考
  • VSCode 精准控制 Copilot 补全:按语言与场景灵活配置
  • 数据结构:二叉树初阶与实现
  • AI Agent Skills 资源合集:支持 Cursor、Claude Code 与 Copilot 的一键部署方案

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online