第1章 网络编程基础
从单机与网络游戏的状态边界出发,贯通IP、TCP/IP以及阻塞和非阻塞Socket,为后续框架建立可分片、可重组的字节流契约。
直觉:先找唯一事实
从单机与网络游戏的状态边界出发,贯通IP、TCP/IP以及阻塞和非阻塞Socket,为后续框架建立可分片、可重组的字节流契约。 真正的难点不是把接口调用成功,而是让每次输入只产生一份事实,旧连接、旧实体、旧进程和旧定时器不能越过代际边界。先预测:如果只保留最终成功截图,本章最可能隐藏哪一种重复执行、状态污染或资源泄漏?
权威目录定位
本页按完整公开目录追踪以下条目;编号和名称用于锁定原书范围,正文是独立教学重构,不复制原书段落:
- 1.1 单机游戏与网络游戏的区别
- 1.2 理解IP地址
- 1.3 理解TCP/IP
- 1.4 阻塞式网络编程
- 1.5 非阻塞网络编程
- 1.6 总结
本章从“1.1 单机游戏与网络游戏的区别”进入,以“1.6 总结”收束。现代安全、可观察性和故障演练作为教学补充单独标明,不会被登记成原书分节。
核心概念与所有权
、、、、。 这些概念要同时回答四个问题:谁创建输入,谁拥有可变状态,什么代际拒绝旧结果,失败后谁回滚或补偿。
| # | 概念 | 工程含义 |
|---|---|---|
| 1 | 权威状态 | 由服务器拥有并裁决、客户端只能通过输入请求改变的游戏事实。 |
| 2 | 端点 | 由IP地址、端口和传输协议共同标识的通信终点。 |
| 3 | TCP字节流 | 可靠有序但没有应用消息边界的双向字节序列。 |
| 4 | 阻塞I/O | 调用在操作完成或失败前占用当前执行线程的I/O方式。 |
| 5 | 非阻塞I/O | 调用立即返回并用就绪事件驱动后续读写的I/O方式。 |
目录主线与因果关系
1. 1.1 单机游戏与网络游戏的区别
这一段从“1.1 单机游戏与网络游戏的区别”推进到“1.2 理解IP地址”,覆盖1.1 单机游戏与网络游戏的区别、1.2 理解IP地址。先确定输入来源和状态所有者,再明确中间版本、输出以及失败补偿。相邻目录条目不是并列清单:前项提供后项的前置条件,越序输入必须在第一个不满足的阶段被拒绝。
验证时固定客户端、服务端、配置和协议版本,保存请求ID、实体或会话代际、队列水位、状态摘要和恢复动作。若相同输入不能重放,最终结果看起来正确也不能证明本段机制成立。
2. 1.3 理解TCP/IP
这一段从“1.3 理解TCP/IP”推进到“1.4 阻塞式网络编程”,覆盖1.3 理解TCP/IP、1.4 阻塞式网络编程。先确定输入来源和状态所有者,再明确中间版本、输出以及失败补偿。相邻目录条目不是并列清单:前项提供后项的前置条件,越序输入必须在第一个不满足的阶段被拒绝。
验证时固定客户端、服务端、配置和协议版本,保存请求ID、实体或会话代际、队列水位、状态摘要和恢复动作。若相同输入不能重放,最终结果看起来正确也不能证明本段机制成立。
3. 1.5 非阻塞网络编程
这一段从“1.5 非阻塞网络编程”推进到“1.6 总结”,覆盖1.5 非阻塞网络编程、1.6 总结。先确定输入来源和状态所有者,再明确中间版本、输出以及失败补偿。相邻目录条目不是并列清单:前项提供后项的前置条件,越序输入必须在第一个不满足的阶段被拒绝。
验证时固定客户端、服务端、配置和协议版本,保存请求ID、实体或会话代际、队列水位、状态摘要和恢复动作。若相同输入不能重放,最终结果看起来正确也不能证明本段机制成立。
六阶段证据链
本章的可操作链条是:划分单机与网络职责 → 解析IP和端点 → 建立TCP连接 → 循环处理部分收发 → 切换非阻塞模式 → 断线重连后签发。正常样本证明能力,边界样本证明预算,失败样本证明拒绝,恢复样本证明没有留下第二份事实。
最小实现骨架
下面的代码是用于复现实验的独立最小骨架,不是原书源码复制;生产实现还要补齐超时、错误分类、指标和资源清理。
std::vector<std::byte> receive_frame(Socket& socket) {
Header header = read_exact(socket, sizeof(Header));
validate_length(header.length);
return read_exact(socket, header.length);
}同时保存阶段轨迹,不能只看最终返回值:
trace_id,stage,request_id,generation,state_version,budget,decision
baseline-01,划分单机与网络职责,42,7,1,normal,accept
boundary-01,循环处理部分收发,43,7,2,limit,accept
failure-01,断线重连后签发,44,6,2,exceeded,reject每个样本从相同夹具开始,只改变一个故障变量:
for sample in [baseline, boundary, failure, recovery]:
reset_fixture(seed = 20260716)
run_same_script(sample)
assert_single_owner_and_current_generation()
assert_bounded_queue_and_memory()
export_first_divergence_and_recovery()可复现实验
让代理按1、3、7和随机字节边界切分同一消息,先预测阻塞与非阻塞实现的首个差异,再保存返回值、系统错误码和累计缓冲区。 保存编译版本、配置摘要、协议版本、随机种子、请求序号、首偏离节点、恢复动作和最终决策。平均吞吐只能说明趋势,不能证明关键状态没有重复或丢失。
两个必须主动制造的失败
验收矩阵
| 样本 | 输入变化 | 预期状态 | 通过条件 |
|---|---|---|---|
| 正常 | 合法版本、身份和容量 | 六阶段顺序完成 | 双端摘要和状态版本一致 |
| 边界 | 临界时序、容量、重复或切换 | 达到预算但不越界 | 无无限队列和第二份事实 |
| 失败 | 畸形、旧代际、断线或依赖失效 | 在首偏离点停止 | 明确拒绝、补偿或回滚 |
| 恢复 | 修复后重放同一输入 | 收敛到正常轨迹 | 无幽灵状态和资源泄漏 |
本页签发不变量是:连接有唯一所有者;TCP按字节流累积;暂不可读与断线可区分;任何分片下消息结果一致。 任何单次演示、截图或平均指标都不能替代代际、序号、状态摘要和恢复证据。
练习
小结
- 权威状态:由服务器拥有并裁决、客户端只能通过输入请求改变的游戏事实。
- 端点:由IP地址、端口和传输协议共同标识的通信终点。
- TCP字节流:可靠有序但没有应用消息边界的双向字节序列。
- 阻塞I/O:调用在操作完成或失败前占用当前执行线程的I/O方式。
- 非阻塞I/O:调用立即返回并用就绪事件驱动后续读写的I/O方式。
- 六阶段机制链已经映射到正常、边界、失败和恢复证据。
- 公开目录条目已逐项列出,随书源码与现代补充不会冒充原书分节。