CMU 15-213 CSAPP:网络编程与 Web 服务器的底层构建(Network)

发布时间:2026/9/29 2:29:38

CMU 15-213 CSAPP:网络编程与 Web 服务器的底层构建(Network)
写在前面前面我们探讨了内存、汇编、异常控制流和本地 I/O现在我们要把视线投向外部世界。网络编程其实并不神秘在 Unix 的“万物皆文件”哲学下网络连接不过就是一个特殊的文件描述符Socket fd。在这篇笔记中我们将从底层的以太网聊起一步步搭建起 Socket 管道最后亲手解剖一个真实的 Web 服务器是如何运作的。Lec 21 Network Programming Part 1服务端 客户端 事务 (Client-Server Transaction)几乎所有的网络应用都是基于 Client-Server 模型的。Server (服务端):管理资源Resource提供服务Service。它像一台自动售货机永远在被动等待并响应请求。Client (客户端):主动发起请求获取服务。注意Client 和 Server 是进程 (Process)的概念而不是机器的概念。一台物理主机上可以同时跑着成百上千个 Client 和 Server 进程比如亚马逊的服务器群。最底层以太网段管理在最底层的硬件层面以太网Ethernet负责把数据从一台机器搬到另一台机器。MAC 地址:每块网卡出厂时都有一个全球唯一的 48 位地址如00:16:EA:54:54:E6。Hub (集线器) 与数据帧 (Frames):在早期的以太网中主机把数据切成小块Frames发给 HubHub 会极其“无脑”地把这个 Frame 复制并广播给所有连在上面的端口。所有的网卡都会收到这个 Frame但只有发现 MAC 地址和自己匹配的网卡才会把它接收进内存。因特网应用的硬件软件管理TCP/IP 协议栈是构建在底层局域网之上的跨网络抽象它对上层应用屏蔽了底层物理网络的复杂性。IPv4 IPv6IPv4:32 位地址约 43 亿个。最初设计时没人能想到互联网会这么庞大导致地址早已枯竭。由于 NAT (网络地址转换) 技术的续命目前世界上绝大多数的流量依然跑在 IPv4 上。IPv6:128 位地址。号称“能给地球上的每一粒沙子分配一个 IP”。在现代网络编程中我们应该尽量编写协议无关 (Protocol-Independent)的代码让系统自己去适配 IPv4 还是 IPv6。DNS (域名解析系统)人类记不住 IP 地址只能记住域名如www.cmu.edu。DNS 就是互联网的电话本。它是一个庞大的分布式数据库从未命名的根节点开始逐层向下解析.edu - cmu - www最终将域名转化为机器认识的 IP 地址。著名的 Port (端口) 和 Service Name一台主机只有一个 IP但上面可能跑着 Web 服务、邮件服务和 SSH 服务。为了区分数据包该交给哪个进程引入了端口 (Port)的概念16位0~65535。IP 地址找大楼 端口号找房间 唯一的通信端点Socket。知名端口Well-known ports通常被保留定义在 Linux 的/etc/services文件中Echo:7SSH:22Email (SMTP):25Web (HTTP):80Socket Interface (核心打通管道)这是网络编程的灵魂理解 Socket 最好的方法是**“打电话模型”**。1.socket()建立管道 —— 【买一部手机】创建一个 Socket 文件描述符 (fd)。参数domain(IPv4/IPv6),type(一般是流式SOCK_STREAM即 TCP),protocol(一般为 0)。2.bind()绑定端口 —— 【去营业厅办一个手机号】服务端专用。内核把你的 Socket fd 和一个具体的本地 IP 及端口号绑定。告诉系统“如果有发往 80 端口的数据包请交给我。”3.listen()监听端口 —— 【开机调大铃声准备接听】服务端专用。默认创建的 Socket 是主动去连别人的Client 视角。调用listen会把这个 Socket 转换成被动监听模式。backlog: 这是一个“候诊室”的大小。如果并发连接太多服务器处理不过来最多允许多少个连接在队列里排队。4.accept()服务端接受请求 —— 【接起电话开启通话子频道】服务端阻塞在这里直到有客户端连进来。灵魂设定accept会返回一个全新的 Socket fd (connfd) 用来专门和这个客户进行数据收发而原来的监听 fd (listenfd) 继续保持监听状态等待下一个客户进来。5.connect()客户端发起连接 —— 【拨打号码】客户端主动向 Server 发起连接引发 TCP 三次握手。成功后clientfd就可以自由地read/write交流了。现代的地址转换神器getaddrinfo以前写网络代码要自己查 DNS 把域名转成 IP还要手工处理字节序转换大端转小端极其痛苦。现在我们使用getaddrinfo。它是线程安全的可重入不仅通吃 IPv4 和 IPv6而且直接吐出一个链表里面包含了创建 Socket 需要的所有参数。常见套路顺着链表遍历挨个尝试socket()和connect()或bind()直到成功为止。Lec 22 Network Programming Part IISocket Address Structures (令人抓狂的 C 语言强转)C 语言没有面向对象的多态。网络 API 要求传入一个通用的sockaddr结构但我们实际操作时用的是专属的sockaddr_in针对 IPv4。所以你在代码里会看到满天飞的强制类型转换(struct sockaddr *)。这纯粹是历史遗留的丑陋设计习惯就好。Socket Helper封装open_listenfd为了不每次都写一堆繁琐的 Socket 初始化代码CSAPP 提供了一个极为好用的 Helper 包装函数。核心避坑指南 (SO_REUSEADDR):留意幻灯片里的setsockopt行。如果你杀掉一个服务端程序然后马上重启系统常常会报错“Address already in use (地址已被占用)”。因为操作系统会把刚才的端口保持在TIME_WAIT状态一段时间以防残留包。加上SO_REUSEADDR标志可以消除这个恶心的错误允许你立即重启绑定同一端口。迭代 Echo Server (Iterative Server)这是一个最基础的服务端架构。while(1)循环里不断地accept把收到的数据原封不动发回去Echo。它的致命弱点因为是串行Iterative的一次只能处理一个客户。如果黑客 A 连上之后故意不发数据也不挂断整个服务器就完全阻塞挂死了其他任何人都连不进来。这就是为什么后面必然要学习**并发服务器多进程/多线程/I/O 多路复用**的原因。Web (HTTP 原理初探)我们在浏览器里看到的五彩斑斓的网页本质上都是文本和二进制字节流。通过 MIME 扩展类型如text/html,image/jpeg服务器告诉浏览器发过去的数据到底该如何渲染。访问网页其实就是访问服务器硬盘上的一个文件并把它读过来。HTTP 请求 (Requests) 响应 (Responses)HTTP 是一个无状态的纯文本协议非常容易阅读。请求行Method URI Version例如GET /index.html HTTP/1.1响应行Version Status Code Status Msg例如HTTP/1.1 200 OK或HTTP/1.1 404 Not Found在头部之后会跟着一个空行\r\n空行之后就是真正的网页内容体Body了。小操作TINY Web Server 的逻辑实现一个简单的 Web 服务器其实只需这几步建立 Socket 等待连接accept。从连接中读取客户端发来的文本请求。把字符串切开提取出 Method (GET) 和 URI。判断是静态内容返回一个写死的 HTML 文件还是动态内容执行一个程序把程序的输出返回给客户端。CGI 与dup2的终极黑魔法 (Serving Dynamic Content)如果是动态内容客户端怎么传参数给服务端计算服务端又怎么把算好的结果送回给远方的客户端传参参数被塞在 URI 的问号?后面用分隔。空格会被转义为%20。计算服务器收到请求后调用fork()产生一个子进程。子进程把解析出的参数设置到操作系统的环境变量中然后用我们学过的execve()加载一个独立的 C 语言可执行程序CGI 脚本去运行。那个 C 程序直接用getenv就能拿到参数进行计算最为惊艳的设计 (dup2移花接木)那个独立运行的 C 语言计算程序并不知道什么是网络它只是单纯地计算完毕然后用printf()打印结果。printf()默认是输出到STDOUT(终端显示器) 的。但是在执行execve之前父进程巧妙地调用了dup2(fd, STDOUT_FILENO)。这一招瞬间将标准输出的管道重定向到了网络的 Socket fd上于是那个无辜的子程序调用printf(计算结果是 5)时屏幕上什么也没有这串字符顺着网线飞跃大洋直接出现在了客户端的浏览器屏幕上这就是 Unix 底层抽象的顶级魅力

相关新闻

049、双管正激的占空比限制

049、双管正激的占空比限制

2026/8/23 4:17:00

049 双管正激的占空比限制 从一块冒烟的板子说起 去年帮朋友调试一款48V转12V/20A的通信电源,用的是双管正激拓扑。样机第一次上电,轻载正常,加到10A负载,MOS管炸了,驱动芯片也挂了。拆下来看,两个MOS管的漏源极都短路了,变压器初级绕组有烧焦痕迹。 朋友说:“我算过…

使用yolo11训练无人机视角罂粟检测数据集VOC+YOLO格式3648张1类别步骤和流程

使用yolo11训练无人机视角罂粟检测数据集VOC+YOLO格式3648张1类别步骤和流程

2026/8/23 4:17:00

【数据集介绍】 注意数据集中存在增强图片主要是旋转增强,占据数据量大约一半,注意查看图片 数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量…

048、双管正激变换器原理

048、双管正激变换器原理

2026/8/23 4:17:00

048、双管正激变换器原理 上个月帮朋友救一个项目,48V转12V/20A的电源模块,单管正激拓扑,MOS管和续流二极管烧了一轮又一轮。客户催得紧,朋友急得嘴角起泡。我拿到板子一看,复位绕组和漏感尖峰处理得稀碎,MOS管关断瞬间电压应力直接飙到200V+,管子不炸才怪。后来改成双…

CANN/GE ACL数据集缓冲区添加函数

CANN/GE ACL数据集缓冲区添加函数

2026/9/28 4:08:17

aclmdlAddDatasetBuffer 【免费下载链接】ge GE(Graph Engine)是面向昇腾的图编译器和执行器,提供了计算图优化、多流并行、内存复用和模型下沉等技术手段,加速模型执行效率,减少模型内存占用。 GE 提供对 PyTorch、Te…

用ffmpeg高效批量调整图片尺寸的实战指南

用ffmpeg高效批量调整图片尺寸的实战指南

2026/9/28 16:01:49

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

Transformers 音频特征提取工具库 audio_utils 全解析:从 Mel 刻度换算到对数 Mel 频谱

Transformers 音频特征提取工具库 audio_utils 全解析:从 Mel 刻度换算到对数 Mel 频谱

2026/9/28 2:15:29

Transformers 音频特征提取工具库 audio_utils 全解析:从 Mel 刻度换算到对数 Mel 频谱 【免费下载链接】transformers 🤗 Transformers: the model-definition framework for state-of-the-art machine learning models in text, vision, audio, and mu…

RustFS 多节点集群重启与滚动升级实战:Readiness、Quorum 与 Degraded 模式完全指南

RustFS 多节点集群重启与滚动升级实战:Readiness、Quorum 与 Degraded 模式完全指南

2026/9/28 3:14:54

RustFS 多节点集群重启与滚动升级实战:Readiness、Quorum 与 Degraded 模式完全指南 【免费下载链接】rustfs 🚀2.3x faster than MinIO for 4KB object payloads. RustFS is an open-source, S3-compatible high-performance object storage system sup…

Java Integer缓存揭秘:128陷阱原理、避坑与面试全解

Java Integer缓存揭秘:128陷阱原理、避坑与面试全解

2026/9/28 3:58:00

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

RustFS Scanner 数据用量发布权威性决策:配额准入如何获得可用的权威依据

RustFS Scanner 数据用量发布权威性决策:配额准入如何获得可用的权威依据

2026/9/28 3:47:14

RustFS Scanner 数据用量发布权威性决策:配额准入如何获得可用的权威依据 【免费下载链接】rustfs 🚀2.3x faster than MinIO for 4KB object payloads. RustFS is an open-source, S3-compatible high-performance object storage system supporting mi…

远程协作的工作台整理

远程协作的工作台整理

2026/9/28 16:01:48

远程协作的工作台整理远程协作的核心不是再加一个工具,而是让交接信息足够完整。异步任务要写明目标、输入位置、完成标准和需要决策的人。 工作台的最小配置 将日程、待办、代码和沟通入口收拢到少数固定位置;通知按紧急程度分层。工作台不需要模仿办公…

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

2026/9/28 5:05:21

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

2026/9/28 16:01:48

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…