第 7 章 · 01 socket 编程:TCP 监听与连接 本节摘要:HTTP 跑在 TCP 上,所以造 Web 服务器的第一步是学会 socket 编程。本节导读服务端 socket 的经典四步: (建 fd)、 (绑端口)、 (开始监听)、 (接受连接,返回新 fd)。理解这套调用,你就理解了「一个网络服务器如何接到客户端连接」——它是第 2 章(造 Shell)fork/exec 之外,又一个系统编程的核心原语。 内容来源:基于「Build your own X」Web Server 域整理的导读,呼应姊妹篇《Linux 命令》第 6、7 章。 学习目标 阅读完本节,你应当能够: 说清服务端 socket 的四步:socket、bind、listen、accept。
本节摘要:HTTP 跑在 TCP 上,所以造 Web 服务器的第一步是学会 socket 编程。本节导读服务端 socket 的经典四步:
socket(建 fd)、bind(绑端口)、listen(开始监听)、accept(接受连接,返回新 fd)。理解这套调用,你就理解了「一个网络服务器如何接到客户端连接」——它是第 2 章(造 Shell)fork/exec 之外,又一个系统编程的核心原语。
内容来源:基于「Build your own X」Web Server 域整理的导读,呼应姊妹篇《Linux 命令》第 6、7 章。
阅读完本节,你应当能够:
socket 是网络编程的「入口」——所有 TCP/UDP 服务都从它开始。理解 socket 四步,你打开了网络编程的大门:Web 服务器、聊天服务、游戏服务器、消息队列,都建立在 socket 上。本节呼应姊妹篇《Linux 命令》第 6 章(文件描述符)——socket 也是一种 fd,第 7 章(ss 看监听端口)——你造的服务器要能被 ss 看到。
1. socket(AF_INET, SOCK_STREAM, 0) ── 创建一个 TCP 套接字, 得到 fd(比如 fd=3) 2. bind(fd, {端口 8080}, ...) ── 把 fd 绑到某端口, 告诉内核"这个端口归我管" 3. listen(fd, backlog) ── 标记这个 fd 为"被动套接字", 开始接受连接; backlog 是等待队列长度 4. accept(fd, ...) → 返回新 fd(比如 fd=4) ── 阻塞等待, 有客户端连接时, 返回一个"新 fd"代表这条连接 ── 原 fd(3)继续监听, 新 fd(4)用于与这个客户端收发数据
这是 socket API 一个关键设计:一个「监听 fd」负责等连接,每来一个连接,accept 吐出一个「连接 fd」专门对付这条连接。监听 fd 永远只管 accept,连接 fd 只管收发。这样服务器能同时管很多连接(每个一条 fd)。
拿到连接 fd 后,用 recv(fd, buf)(读)和 send(fd, buf)(写),就像读写文件——因为 socket 是 fd,接口统一。这正是 Unix「一切皆文件描述符」的体现。
客户端用 connect(fd, 服务器地址),建立连接后直接 send/recv。本书聚焦服务端,客户端概念上更简单。
fd = socket(AF_INET, SOCK_STREAM) setsockopt(SO_REUSEADDR) # 重启时端口可立即重用(否则 TIME_WAIT 卡一会) bind(fd, 端口 8080) listen(fd, 10) while True: conn_fd = accept(fd) msg = recv(conn_fd) send(conn_fd, "Hello!") close(conn_fd)
用 curl 或 nc localhost 8080 测试连接。
nc localhost 端口 测试能收到连接并回应。下一节讲 HTTP 请求解析——把收到的字节变成结构化请求。