跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++

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

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

PgDevote发布于 2026/3/23更新于 2026/10/2585 浏览
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. 总结

更多推荐文章

查看全部
  • OpenClaw 开源 AI 助手平台架构与部署指南
  • OpenClaw 开源助手变现案例:10 个真实模式与部署指南
  • VMware 虚拟机安装 Ubuntu 图文教程
  • Python 输入 input 函数及字符串处理:大小写与 strip()
  • Dify 工作流发布为 MCP Server 实战指南
  • Cursor 集成 MCP 服务实战:环境配置与自动化应用
  • DeepSeek AI 工具功能与编程辅助能力介绍
  • Llama3.1 大模型 LoRA 微调实战教程
  • MCPo:将 MCP 协议转换为 OpenAPI 的代理服务器及集成方案
  • 国内环境升级 GitHub Copilot 专业版支付方案
  • Linux 进程间通信进阶:管道与共享内存详解
  • 薛定谔优化算法原理与实现
  • Cursor Visual Editor 评测:Web 开发如何回归所见即所得
  • C++ 类与对象:封装特性的实现与实战应用
  • ToDesk 顺网云海马云部署 DeepSeek 大模型对比评测
  • DAMO-YOLO 工业视觉部署:深色模式与异步渲染实战
  • 双盲评审期间如何制作匿名 GitHub 仓库链接
  • 深度学习模型优化策略与实战调参
  • Heygem 数字人系统 Linux 环境依赖安装步骤
  • OpenJDK 安装与配置图文详解

相关免费在线工具

  • 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