第0章 [快速入门]网络游戏编程:网络和游戏编程的技术基础
从OSI、套接字、并发连接、事件驱动和RPC进入网络编程,再用无多线程任务系统连接到游戏主循环。
直觉:先找系统边界
从OSI、套接字、并发连接、事件驱动和RPC进入网络编程,再用无多线程任务系统连接到游戏主循环。 真正的难点不是记住术语,而是让每份可变状态、每笔成本和每个恢复动作都有明确责任。先预测:如果只保留最终成功截图,本页最可能隐藏哪一种重复处理、状态分叉或失主资源?
权威目录定位
本页依据公开电子书目录锁定原书范围。编号和名称用于一对一追踪,正文是独立教学重构,不复制原书段落;现代安全、可观察性与故障演练会明确作为教学补充:
- 0.1 网络游戏开发者所需了解的网络编程基础
- 0.1.1 网络编程是必需的
- 0.1.2 网络编程与互联网编程
- 0.1.3 互联网编程的历史和思想
- 0.1.4 OSI参考模型——透明地处理标准和硬件的变化
- 0.1.5 网络游戏系统及其层次结构
- 0.1.6 套接字API的基础知识
- 0.1.7 网络游戏和套接字API——使用第4层的套接字API
- 专栏 网络编程的特性和游戏架构的关系——服务器、客户端所需具备的性能和功能
- 0.2 套接字编程入门——处理多个并发连接、追求性能
- 0.2.1 通信链路的确定(复习)
- 0.2.2 套接字API基础——一个简单的ECHO服务器、ECHO客户端示例
- 0.2.3 TCP通信链路的状态迁移和套接字API
- 0.2.4 处理多个并发连接——通向异步套接字API之路
- 0.2.5 同步调用(阻塞)和线程
- 0.2.6 单线程、非阻塞、事件驱动——使用select函数进行轮询
- 0.2.7 网络游戏输入输出的特点——单线程、事件驱动、非阻塞
- 0.2.8 网络游戏和实现语言
- 0.2.9 充分发挥性能和提高开发效率——从实现语言到底层结构
- 0.2.10 发挥多核服务器的性能
- 专栏 输入输出的实现方针和未来提高性能的可能性
- 0.2.11 多核处理器与网络吞吐量——网络游戏与小数据包
- 0.2.12 简化服务器实现——libevent
- 0.3 RPC指南——最简单的通信中间件
- 0.3.1 通信库的必要性
- 0.3.2 网络游戏中使用的RPC的整体结构
- 0.3.3 [补充]UDP的使用
- 0.4 游戏编程基础
- 0.4.1 游戏编程的历史
- 0.4.2 采用“只要能画点就能做出游戏”的方针来开发入侵者游戏
- 0.4.3 游戏编程的基本剖析
- 0.4.4 游戏编程精粹——不使用线程的“任务系统”
- 0.4.5 两种编程方法的相似性——不使用线程
- 0.5 小结
- 专栏 确保开发效率和各平台之间的可移植性
本页共追踪 35 个公开分节。追踪入口从“0.1 网络游戏开发者所需了解的网络编程基础”开始,以“专栏 确保开发效率和各平台之间的可移植性”收束。
核心概念与所有权
、、、、。 这些概念必须同时回答四个问题:谁创建输入,谁拥有可变状态,哪个版本拒绝旧结果,失败后谁回滚或补偿。
| # | 概念 | 工程含义 |
|---|---|---|
| 1 | 套接字 | 操作系统暴露给应用程序的网络通信端点接口。 |
| 2 | 非阻塞I/O | 调用立即返回,并由就绪事件驱动后续读写的输入输出方式。 |
| 3 | 事件驱动 | 围绕可读、可写和定时事件推进连接状态机的执行模型。 |
| 4 | RPC | 把跨进程消息封装成近似本地函数调用契约的通信机制。 |
| 5 | 任务系统 | 在单线程游戏循环中按帧更新多个逻辑任务的调度结构。 |
目录主线与因果关系
1. 从分层到端点
OSI模型用于隔离变化,游戏进程真正依赖的是传输层端点与套接字状态。协议要先定义长度、版本和错误,再讨论业务字段。
先预测:如果省略这一层,正常样本可能仍然成功,但边界或故障样本会在哪个状态首先偏离?
2. 事件循环连接网络与游戏
select或libevent只报告就绪,不承诺一次读完。连接状态机负责累积字节、解析完整帧、限制队列;任务系统则在固定预算内消费已验证消息。
先预测:如果省略这一层,正常样本可能仍然成功,但边界或故障样本会在哪个状态首先偏离?
3. RPC不是隐藏网络
RPC减少样板代码,但超时、重复、乱序和断线仍然存在。每个调用必须有请求ID、期限、幂等语义和可观察结果。
先预测:如果省略这一层,正常样本可能仍然成功,但边界或故障样本会在哪个状态首先偏离?
六阶段证据链
本页的可操作链条是:分层定位 → 建立套接字 → 处理部分收发 → 接入事件循环 → 封装RPC → 任务循环签发。正常样本证明能力,边界样本证明预算,失败样本证明拒绝,恢复样本证明没有留下第二份事实。
最小实现骨架
下面是用于复现实验的独立骨架,不是原书代码复制;生产实现还需补齐平台差异、权限、安全和资源清理。
void on_readable(Connection& c) {
while (auto chunk = c.socket.try_read()) {
c.buffer.append(*chunk);
while (auto frame = decode_complete_frame(c.buffer)) {
rpc.dispatch(validate(*frame));
}
}
}证据记录必须把决策与原始指标放在一起:
book: 网络游戏核心技术与实战
page: gnc-00-quickstart-network-game-programming
catalog_entries: 35
sample: normal | boundary | failure | recovery
state_owner: explicit
first_divergence: null
recovery_action: replay_same_input故障脚本只改变一个变量,并保留恢复阶段:
baseline -> inject(把一次recv当成一条完整消息,分片或粘包时解析越界。)
observe -> stop_at_first_divergence
recover -> replay_same_version_and_input
assert -> no_duplicate_state && no_orphan_resource常见误区与故障注入
验收矩阵
| 样本 | 输入变化 | 预期状态 | 通过条件 |
|---|---|---|---|
| 正常 | 合法版本、身份、顺序和容量 | 六阶段顺序完成 | 状态摘要与所有权一致 |
| 边界 | 临界时序、容量、重复或切换 | 达到预算但不越界 | 无无限队列和第二份事实 |
| 失败 | 畸形、旧版本、断线或依赖失效 | 在首偏离点停止 | 明确拒绝、补偿或回滚 |
| 恢复 | 修复后重放同一输入 | 收敛到正常轨迹 | 无幽灵状态和资源泄漏 |
本页签发不变量是:每个连接只有一个状态所有者;部分读写不破坏消息边界;网络事件与游戏任务都不阻塞主循环。 任何单次演示、截图或平均指标都不能替代版本、状态摘要、首偏离点和恢复证据。
练习
小结
- 套接字:操作系统暴露给应用程序的网络通信端点接口。
- 非阻塞I/O:调用立即返回,并由就绪事件驱动后续读写的输入输出方式。
- 事件驱动:围绕可读、可写和定时事件推进连接状态机的执行模型。
- RPC:把跨进程消息封装成近似本地函数调用契约的通信机制。
- 任务系统:在单线程游戏循环中按帧更新多个逻辑任务的调度结构。
- 六阶段机制链已经映射到正常、边界、失败和恢复证据。
- 公开目录已逐项追踪,现代补充不会冒充原书分节。