秋雨De blog

  • 首页
  • 留言板
  • 关于
  • rss
秋雨De blog
一个技术小白的个人博客
  1. 首页
  2. 未分类
  3. 正文

《手写 C++ Web 服务器》:从 TCP 套接字到请求处理

2026年3月12日 77点热度 0人点赞 0条评论

从高中开始,我就对 0 和 1 构建出的庞大计算机体系充满震撼——那些冰冷的二进制数字,居然能搭建起如今包罗万象的互联网世界。那时候,我天真地想彻底搞明白“0 和 1 如何构建这一切”,但很快就发现,计算机的复杂度远超我的想象。操作系统、编译器、网络协议、分布式系统……每一层都像一座座高山,初学者几乎无法一口吃下全部知识。

于是,我决定退而求其次,从最基础的网络编程入手:先学 Socket 开发,理解数据如何在网络中传输;再一步步尝试,亲手实现一个属于自己的 Web 服务器。经过几个月的学习与实践,我完成了第一版轻量级 C++ Web 服务器。它基于 Boost.Asio,能够异步监听 TCP 端口、解析 HTTP 请求、返回响应,并通过线程池处理并发连接。为了方便大家学习,我已经将完整代码开源:https://github.com/Fall-Rain/asio_web_service

本篇文章将基于最初提交的代码,从 TCP 服务器搭建、Session 异步请求处理 到 响应发送,带大家了解手写 C++ Web 服务器的基础骨架。


一、TCP 服务器骨架

服务器入口在 main.cpp 中:

boost::asio::io_context io_context;
Server server(io_context, 8090);
server.start();
io_context.run();
server.stop();

流程解析:

  1. io_context:Boost.Asio 的核心 I/O 对象,用于管理所有异步操作。
  2. Server:封装了 TCP 端口监听、异步接受连接和线程池分发任务。
  3. start() / stop():分别用于启动监听和线程池,以及关闭服务器。
  4. io_context.run():进入事件循环,等待连接、读取和写入操作的回调执行。

Server 的核心:异步接受连接

void Server::do_accept() {
     acceptor_.async_accept([this](std::error_code ec, boost::asio::ip::tcp::socket socket) {
        if (!ec) {
            pool.post([session = std::make_shared<Session>(socket)] {
                session->start();
            });
        }
        do_accept();
    });
}

解析:

  • async_accept 非阻塞等待客户端连接,连接到来时触发回调
  • 每个连接创建一个 Session 对象,独立处理请求
  • pool.post() 将任务放入线程池,提高并发处理能力
  • 递归调用 do_accept() 实现循环监听下一连接

二、Session:单连接生命周期管理

每个客户端连接对应一个 Session 对象,负责管理从接收请求到发送响应的完整流程。

Session::Session(boost::asio::ip::tcp::socket &socket): client_socket_(std::move(socket)) {}
  • 保存 TCP 套接字 client_socket_
  • 使用 std::move 确保 socket 唯一所有权

异步读取请求

void Session::do_read() {
    boost::asio::async_read_until(client_socket_, client_buffer_, "\r\n\r\n",
        [self = shared_from_this()](std::error_code ec, std::size_t bytes_transferred) {
            if (!ec) {
                // 解析请求头
                ...
                self->do_write();
            }
        }
    );
}
  • async_read_until 异步读取,直到遇到 HTTP 报文结束标识 \r\n\r\n
  • 回调中使用 shared_from_this() 保证对象在异步回调期间不会被销毁
  • 解析请求头,读取请求体(如 POST 请求)

请求头解析逻辑

std::string request_header(boost::asio::buffers_begin(self->client_buffer_.data()),
                           boost::asio::buffers_begin(self->client_buffer_.data()) + bytes_transferred);
boost::split(headers, request_header, boost::is_any_of("\r\n"), boost::token_compress_on);
  • 将请求头按行拆分
  • 第一行解析 HTTP 方法、URI、版本
  • 其他行解析为键值对存入 header_map

请求体读取

auto content_length = self->header_map.find("Content-Length");
if (content_length != self->header_map.end()) {
    ...
    boost::asio::read(self->client_socket_, boost::asio::buffer(buffer),
                      boost::asio::transfer_exactly(content_length - self->request_body.size()), error);
    ...
}
  • 判断请求是否有 body
  • 根据 Content-Length 精确读取请求体

三、发送响应

void Session::do_write() {
    std::ostringstream response_stream;
    response_stream << "HTTP/1.1 200 OK\r\n";
    response_stream << "Content-Type: text/html\r\n";
    response_stream << "Content-Length:" << self->request_body.size() << "\r\n";
    response_stream << "\r\n";
    response_stream << self->request_body;    boost::asio::async_write(client_socket_, boost::asio::buffer(response_stream.str()),
        [self = shared_from_this()](std::error_code ec, std::size_t length) {
            if (ec) std::cerr << "write error: " << ec.message() << std::endl;
        });
}
  • 将请求体原样返回客户端,便于测试
  • 使用 async_write 异步发送响应,提高服务器吞吐量

四、线程池支持高并发

ThreadPool::ThreadPool(std::size_t size) : work_(io_context_) {
    for (std::size_t i = 0; i < size; ++i) {
        threads_.emplace_back([this] { io_context_.run(); });
    }
}
  • 固定数量线程运行 io_context.run()
  • 每个线程可以处理异步操作回调,提高并发处理能力
  • stop() 停止所有线程并回收资源

五、小结与开源链接

通过这一版服务器,你可以看到完整的数据流:

客户端 → TCP 套接字 → Session → 请求解析 → 响应 → 客户端

虽然功能简单,但它涵盖了 C++ Web 服务器的核心概念:

  • 异步 TCP 监听
  • Session 生命周期管理
  • HTTP 请求头解析与请求体读取
  • 异步响应发送
  • 线程池并发处理

这套服务器代码已经开源,大家可以在 GitHub 上直接下载、编译和调试:https://github.com/Fall-Rain/asio_web_service

在后续文章中,我会讲解如何进一步封装路由、添加中间件和 WebSocket 支持,让服务器逐步从基础骨架成长为可实战使用的轻量级 C++ Web 框架。

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: 暂无
最后更新:2026年3月12日

fallrain

种一棵树最好的时间是十年前,其次是现在。

点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

fallrain

种一棵树最好的时间是十年前,其次是现在。

文章目录
  • 一、TCP 服务器骨架
    • Server 的核心:异步接受连接
  • 二、Session:单连接生命周期管理
    • 异步读取请求
    • 请求头解析逻辑
    • 请求体读取
  • 三、发送响应
  • 四、线程池支持高并发
  • 五、小结与开源链接
友情连接
猫饭范文泉博客迎風别葉CODING手艺人ScarSu博友圈
归档
  • 2026 年 3 月
  • 2025 年 11 月
  • 2025 年 5 月
  • 2025 年 4 月
  • 2025 年 3 月
  • 2024 年 12 月
  • 2024 年 10 月
  • 2024 年 5 月
  • 2023 年 2 月
  • 2022 年 11 月
  • 2022 年 3 月
  • 2021 年 12 月
  • 2021 年 8 月
  • 2021 年 5 月
  • 2021 年 4 月
  • 2021 年 3 月
  • 2020 年 12 月
  • 2020 年 11 月
  • 2020 年 8 月
  • 2020 年 5 月
  • 2019 年 12 月
  • 2019 年 3 月

吉ICP备18007356号

吉公网安备22020302000184号

Theme Kratos Made By Seaton Jiang

COPYRIGHT © 2026 秋雨De blog ALL RIGHTS RESERVED