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

Linux 网络编程实战:用 C++ 实现 JSON 解析与 HTTP 服务器

综述由AI生成深入讲解了 C++ 中的 JSON 序列化与反序列化原理,基于 nlohmann/json 库演示了对象操作。随后剖析了 HTTP 协议结构,包括请求行、头部及状态码机制。最后结合 Socket 编程、线程池技术,从零构建了一个支持 GET 和 POST 请求的 Web 计算器服务器,涵盖了文件读取、静态资源服务及动态业务逻辑处理等核心环节。

墨染流年发布于 2026/3/24更新于 2026/5/87 浏览
Linux 网络编程实战:用 C++ 实现 JSON 解析与 HTTP 服务器

引入

在之前的讨论中,我们深入探讨了序列化与反序列化的概念。对于基于 TCP 协议通信的双方,由于 TCP 是面向字节流的,发送数据前通常需要定义一种结构化数据来描述内容。在 C++ 中,这通常表现为对象或结构体。然而,直接将结构体内存中的字节原样发送会引发字节序和内存对齐问题,不同平台或编译器可能导致解析错误。

因此,我们需要借助序列化。序列化是指将结构化数据按预定规则转换为连续字节流,目的是屏蔽平台差异,使不同平台的进程能统一解析该字节流。序列化主要分为文本序列化与二进制序列化。

文本序列化将数据转换为字符串,本质也是连续字节流,不存在字节序问题,但传输体积较大且解析开销高。二进制序列化直接发送原始二进制数据,体积小、解析快,但人类难以阅读。在实际开发中,成熟的第三方库通常能提供更完善的处理方案。

本文重点介绍广泛应用的文本序列化格式——JSON,并在此基础上,结合 Linux 网络编程,从零手搓一个支持 JSON 交互的 Web 计算器服务器。

JSON 基础与实践

JSON(JavaScript Object Notation)是一种轻量级、基于文本、人类可读的数据交换格式。它源于 JavaScript,但已跨语言通用。JSON 本质上符合规范的字符串,支持整型、浮点型、布尔型、字符串、对象及数组等类型。

在 C++ 中,常用的 JSON 库包括 json.hpp(即 nlohmann/json)。它是一个头文件库,无需编译安装,只需将其源码放入项目目录即可使用。

基本操作

json 类位于 nlohmann 命名空间内。创建对象主要有两种方式:列表初始化或直接赋值。

#include "json.hpp"
#include <iostream>

using json = nlohmann::json;

int main() {
    // 方式一:列表初始化
    json j1 = {{"name", "WZ"}, {"age", 20}};
    
    // 方式二:直接赋值(推荐,更符合容器习惯)
    json j2;
    j2["name"] = "WZ";
    j2["age"] = 20;
    
    std::cout << j1.dump() << std::endl; // 紧凑格式
    std::cout << j1.dump(2) << std::endl; // 格式化输出,缩进 2 格
    return 0;
}

dump() 函数用于序列化,返回 std::string。不传参数时生成紧凑格式;传入整数参数则进行格式化缩进。注意,生产环境中通常避免缩进以减少传输体积。

对于数组,同样支持列表初始化或 添加元素。访问和修改字段则通过重载的 运算符实现,这与标准库容器的使用习惯一致。

push_back
[]
反序列化

将 JSON 字符串还原为 json 对象需调用静态成员函数 parse()。C++11 引入了原始字符串字面量 R"(...)" 语法,可方便地构造包含特殊字符的 JSON 字符串而无需转义。

#include "json.hpp"
#include <iostream>

int main() {
    std::string s = R"({"name":"WZ","age":18,"is_student":true})";
    json j = json::parse(s);
    std::cout << j["name"] << std::endl;
    return 0;
}
底层原理简析

json.hpp 内部维护一个 json 类,核心包含类型标签(value_t)和联合体(union)存储的值变量。联合体设计使得同一时刻只能表示一种数据类型,有效管理内存。构造函数根据输入决定类型,对象对应 std::map,数组对应 std::vector。

operator[] 的重载非常关键:接收 std::string 时处理对象键值对,若当前为空则自动转为对象类型;接收 size_t 时处理数组索引,支持自动扩容。此外,类还定义了隐式类型转换运算符(如 operator int()),使得 int age = j["age"] 这样的代码能够正常工作。

HTTP 协议详解

HTTP 作为应用层协议,基于 TCP 传输。理解其报文结构是实现 Web 服务器的基础。

URL 与域名解析

URL(Uniform Resource Locator)由协议、域名、端口、路径等组成。浏览器输入网址后,首先进行域名解析(DNS),将域名转换为 IP 地址。解析过程涉及本地缓存、hosts 文件、本地 DNS 服务器及根/顶级/权威域名服务器的迭代查询。

请求报文结构

HTTP 请求报文分为四部分:请求行、请求头、空行、请求正文。

请求行包含方法、URL 和协议版本。常见方法有 GET(获取资源)、POST(提交数据)等。GET 通常不带正文,数据放在 URL 查询参数中;POST 携带正文,适合提交表单或上传文件。

请求头由多行键值对组成,包含 Host、User-Agent、Content-Type 等信息。Host 字段用于虚拟主机路由,Connection 控制连接状态(keep-alive 或 close)。

响应报文结构

响应报文结构与请求类似,包含响应行、响应头、空行、响应正文。

响应行包含协议版本、状态码和状态描述。状态码首位数字代表类别:1xx 信息性,2xx 成功,3xx 重定向,4xx 客户端错误,5xx 服务器错误。

响应头中常见的 Content-Type 指明正文类型,Content-Length 指明长度。Set-Cookie 用于维持会话状态,解决 HTTP 无状态带来的登录问题。

Web 服务器实战

基于上述理论,我们使用 C++ 构建一个简单的 Web 服务器,支持静态资源服务和动态计算逻辑。

架构设计

服务器采用面向对象设计,封装 Socket 操作于 sock 类中,利用 RAII 管理资源。主逻辑由 Httpserver 类负责,监听指定端口。为了高效处理并发连接,引入线程池解耦连接接受与业务处理。

// sock 类示例:封装 socket 系统调用
class sock {
public:
    void socket() {
        socketfd = ::socket(AF_INET, SOCK_STREAM, 0);
        if (socketfd < 0) { /* 错误处理 */ }
        int opt = 1;
        setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt));
    }
    // ... bind, listen, accept 等方法 ...
private:
    int socketfd;
};
请求解析

TCP 是字节流,读取时需判断完整报文边界。HTTP 请求头以 `

结束。我们循环调用recv` 直到缓冲区包含该标记,再提取请求行和头部。

对于 POST 请求,需根据 Content-Length 头读取完整的请求正文。解析完成后,将数据填充至 Http_Request 结构体,包含方法、URL、Header 及 Body。

bool Get_HttpRequest(size_t socketfd, Http_Request& hr) {
    std::string data;
    char buffer[BUFFER_SIZE];
    while (true) {
        ssize_t read_bytes = recv(socketfd, buffer, BUFFER_SIZE - 1, 0);
        if (read_bytes <= 0) return false;
        data.append(buffer, read_bytes);
        if (data.find("\r\n\r\n") != std::string::npos) break;
    }
    // 进一步解析 Head 和 Body...
    return hr.Deserialization(data.substr(0, data.find("\r\n\r\n") + 4));
}
业务处理

根据请求方法分发处理逻辑:

  1. GET 请求:映射到文件系统。拼接 URL 与根目录路径,读取文件内容。根据文件后缀设置正确的 MIME 类型(如 .html -> text/html)。若文件不存在,返回 404 页面。
  2. POST 请求:解析请求正文中的键值对。本例实现了一个计算器功能,解析 a, b, op 参数,执行算术运算后返回 HTML 结果页。
void run() {
    Http_Request hr;
    if (!Get_HttpRequest(socketfd, hr)) { /* 错误处理 */ return; }
    
    std::string res;
    if (hr.method == "GET") {
        res = Http_Get_Handler(hr);
    } else if (hr.method == "POST") {
        res = Http_Post_Handler(hr);
    } else {
        /* 不支持的方法 */ return;
    }
    
    send(socketfd, res.c_str(), res.size(), 0);
    close(socketfd);
}
线程池与任务调度

主线程负责 accept 新连接,将连接句柄封装为 Task 对象推入线程池队列。工作线程从队列获取任务并执行 run 方法。这种设计避免了频繁创建销毁线程的开销,同时保证了高并发下的响应速度。

结语

本文详细剖析了 JSON 序列化机制与 HTTP 协议规范,并通过 C++ 实现了具备基础功能的 Web 服务器。从 Socket 封装、线程池管理到具体的业务逻辑处理,涵盖了网络编程的核心环节。掌握这些知识,为进一步学习 HTTPS、异步 IO 及高性能框架打下了坚实基础。

目录

  1. 引入
  2. JSON 基础与实践
  3. 基本操作
  4. 反序列化
  5. 底层原理简析
  6. HTTP 协议详解
  7. URL 与域名解析
  8. 请求报文结构
  9. 响应报文结构
  10. Web 服务器实战
  11. 架构设计
  12. 请求解析
  13. 业务处理
  14. 线程池与任务调度
  15. 结语
  • 💰 8折买阿里云服务器限时8折了解详情
  • GPT-5.5 超高智商模型1元抵1刀ChatGPT中转购买
  • 代充Chatgpt Plus/pro 帐号了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

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

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

更多推荐文章

查看全部
  • LeetCode Hot 100 经典题型 Python 刷题记录
  • Stable Diffusion 与 Z-Image-Turbo 部署对比:推理速度与显存占用评测
  • GTE 中文向量模型技术解析、C-MTEB 表现及 WebUI 部署
  • LLaMA Factory 微调 LLMs 与 VLMs 实战指南
  • Python 面向对象进阶:封装、继承、多态与元类详解
  • Stable Diffusion 3.5 FP8 显存优化与消费级 GPU 部署指南
  • 大模型商业化竞争加剧,百度文心实战与营收分析
  • MySQL 数据库约束与设计指南
  • 智谱清影 2.0:AIGC 视频技术突破与产业价值解析
  • 如何在 VS Code 中为 GitHub Copilot 添加 Skill
  • 微信小程序 webview postmessage 通信指南
  • Ubuntu 下 Python 连接 KingbaseES 数据库实现增删改查
  • VSCode AI Copilot 自定义指令配置实战指南
  • SciChart.js v5 发布:Web 图表性能与功能升级
  • 使用 Python 和 WinRM 远程控制 Windows 服务器
  • Python OpenCV 库安装与基础使用方法详解
  • Linux sudo 命令提升权限使用技巧
  • FAIR plus 2026 机器人全产业链链接会技术亮点梳理
  • C++ 二叉搜索树详解:增删查改与 key/value 场景实现
  • Windows Git 安装配置指南:避坑与最佳实践 (2025 版)

相关免费在线工具

  • 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