0Pricing
C++ Academy · 课时

构建 TCP 回显服务器

逐步实现一个完整的 TCP 回显服务器

构建 TCP 回显服务器 是 CoddyKit 上的免费 C++ Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C++ Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C++ Academy 课程共包含 4 节课。

目标

构建一个最小的 TCP 服务器:接受连接、读取字节,再将这些字节写回。这是网络编程中的“Hello World”。

服务器框架

服务器流程是:创建套接字、绑定、监听、接受、处理。无限循环。

int srv = socket(AF_INET, SOCK_STREAM, 0);
bind(srv, (sockaddr*)&addr, sizeof(addr));
listen(srv, 10);
while (true) {
    int client = accept(srv, nullptr, nullptr);
    handle(client);
    close(client);
}

地址复用选项

设置 SO_REUSEADDR,这样服务器无需等待 OS 释放端口即可立即重启。

int yes = 1;
setsockopt(srv, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));

回显循环

将数据读入缓冲区,再将相同的字节写回。当客户端关闭连接时停止。

void handle(int client) {
    char buf[1024];
    while (true) {
        ssize_t n = recv(client, buf, sizeof(buf), 0);
        if (n <= 0) break;          // closed or error
        send(client, buf, n, 0);
    }
}

部分读取与写入

recv 和 send 传输的字节数都可能少于请求的数量。对于基于流的协议,请循环处理,直到操作完成。

ssize_t total = 0;
while (total < n) {
    ssize_t s = send(client, buf + total, n - total, 0);
    if (s <= 0) break;
    total += s;
}

处理多个客户端

最简单的方法是为每个连接创建一个新线程。处理数百个客户端没有问题,但当客户端达到数千个时就会遇到困难。

while (true) {
    int client = accept(srv, nullptr, nullptr);
    std::thread([client]{ handle(client); close(client); }).detach();
}

更好的方式:线程池

随着规模扩大,为每个连接创建线程会浪费资源。使用固定大小的线程池和工作队列可以更好地扩展。

平滑关闭

处理 SIGTERM/SIGINT,以便干净地关闭监听套接字。RAII 还有助于确保所有客户端套接字也都被关闭。

错误处理

请将错误视为预期情况:客户端会断开连接,网络会出现短暂故障,OS 的限制也可能耗尽。记录日志并继续运行,不要因为某个客户端出错就崩溃。

记录每个客户端的日志

记录远程地址,以便进行可观测性分析。

sockaddr_in remote{};
socklen_t len = sizeof(remote);
int client = accept(srv, (sockaddr*)&remote, &len);
char ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &remote.sin_addr, ip, sizeof(ip));
std::cout << "client " << ip << ":" << ntohs(remote.sin_port);

使用 netcat 进行测试

请使用 nc 交互式测试您的回显服务器。

nc 127.0.0.1 8080
hello
hello       # echoed back

超越回显

您可以从回显扩展到:

  • 基于行的协议(类似 HTTP)
  • 带帧的二进制协议(长度前缀)
  • JSON 或 Protobuf 消息

快速检查

SO_REUSEADDR 套接字选项的作用是什么?

回顾

一个最小的 TCP 回显服务器包含:套接字、设置套接字选项 SO_REUSEADDR、绑定、监听,以及循环调用 accept。要处理多个客户端,可以创建线程或使用线程池。要实现大规模扩展,请改用异步 I/O(下一课介绍)。

常见问题解答

「构建 TCP 回显服务器」课时是免费的吗?

是的 — 「构建 TCP 回显服务器」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C++ Academy 课程的其余内容,请升级到 CoddyKit PRO。 C++ Academy 课程共包含 4 节课。

「构建 TCP 回显服务器」这节课中我会学到什么?

逐步实现一个完整的 TCP 回显服务器 你通过在浏览器中直接运行的动手代码来练习 C++ Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 C++ Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 C++ Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。

「构建 TCP 回显服务器」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 C++ Academy 课中编写并运行代码吗?

能。每节 C++ Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. C++ 中的 BSD 套接字 API
  2. 构建 TCP 回显服务器
  3. 使用 epoll 和 kqueue 进行异步 IO
  4. 使用 Boost Asio 实现现代异步 IO
← 返回 C++ Academy