docs: 全面审查并修正所有章节文档内容

- 修正各章节中的错别字和术语错误(如 IPv4 大写规范、接收/接受区分等)
- 补充和完善部分习题答案
- 优化技术描述的准确性和专业性
- 合并所有章节内容到根 README.md

新增文件:
- CLAUDE.md: 项目开发指南
- .claude/agents/content-reviewer.md: 内容审查 subagent
- .claude/agents/merger.md: 文档合并 subagent

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
riba2534
2026-01-05 15:28:29 +08:00
parent f163bca3a9
commit d44ecdf807
23 changed files with 1933 additions and 825 deletions

View File

@@ -30,7 +30,7 @@ IP 层解决数据传输中的路径选择问题,只需照此路径传输数
IP 层只关注一个数据包(数据传输基本单位)的传输过程。因此,即使传输多个数据包,每个数据包也是由 IP 层实际传输的也就是说传输顺序及传输本身是不可靠的。若只利用IP层传输数据则可能导致后传输的数据包B比先传输的数据包A提早到达。另外传输的数据包A、B、C中可能只收到A和C甚至收到的C可能已经损毁 。反之,若添加 TCP 协议则按照如下对话方式进行数据交换。
> 主机A正确接第二个数据包
> 主机A正确接第二个数据包
>
> 主机B知道了
>
@@ -56,7 +56,7 @@ IP 层只关注一个数据包(数据传输基本单位)的传输过程。
#### 4.2.2 进入等待连接请求状态
已经调用了 bind 函数给套接字分配地址,接下来就是要通过调用 listen 函数进入等待接请求状态。只有调用了 listen 函数,客户端才能进入可发出连接请求的状态。客户端可以调用 connect 函数,向服务端请求连接,对于客户端发来的请求,先进入连接请求等待队列,等待服务端受理请求。
已经调用了 bind 函数给套接字分配地址,接下来就是要通过调用 listen 函数进入等待接请求状态。只有调用了 listen 函数,客户端才能进入可发出连接请求的状态。客户端可以调用 connect 函数,向服务端请求连接,对于客户端发来的请求,先进入连接请求等待队列,等待服务端受理请求。
```c
#include <sys/socket.h>
@@ -120,7 +120,7 @@ addrlen: 第二个结构体参数 servaddr 变量的字节长度
注意:**接受连接**不代表服务端调用 accept 函数,其实只是服务器端把连接请求信息记录到等待队列。因此 connect 函数返回后并不应该立即进行数据交换。
客户端在调用connect函数时自动分配主机的IP随机分配端口。无需调用标记的bind函数进行分配。
客户端在调用 connect 函数时自动分配主机的 IP随机分配端口。无需调用显式的 bind 函数进行分配。
#### 4.2.6 回顾 Hello World 客户端
@@ -140,7 +140,7 @@ addrlen: 第二个结构体参数 servaddr 变量的字节长度
![](https://i.loli.net/2019/01/14/5c3c35a773b8c.png)
- 客户端只能等到服务端调用 listen 函数后才能调用 connect 函数
- 客户端只能等到服务端调用 listen 函数后才能调用 connect 函数
- 服务器端可能会在客户端调用 connect 之前调用 accept 函数这时服务器端进入阻塞blocking状态直到客户端调用 connect 函数后接收到连接请求。
### 4.3 实现迭代服务端/客户端
@@ -162,7 +162,7 @@ addrlen: 第二个结构体参数 servaddr 变量的字节长度
- 服务器端在同一时刻只与一个客户端相连,并提供回声服务。
- 服务器端依次向 5 个客户端提供服务并退出。
- 客户端接受用户输入的字符串并发送到服务器端。
- 服务器端将接的字符串数据传回客户端,即「回声」
- 服务器端将接的字符串数据传回客户端,即「回声」
- 服务器端与客户端之间的字符串回声一直执行到客户端输入 Q 为止。
以下是服务端与客户端的代码:
@@ -208,7 +208,21 @@ client:
### 4.4 基于 Windows 的实现
暂略
Windows 平台下的 Socket 编程Winsock与 Linux 平台基本类似,主要区别如下:
1. **头文件**Windows 使用 `winsock2.h``ws2tcpip.h`Linux 使用 `sys/socket.h` 等头文件。
2. **库文件**Windows 需要链接 `ws2_32.lib` 库。
3. **初始化**Windows 使用 Winsock 函数前需要调用 `WSAStartup` 进行初始化,程序结束前需要调用 `WSACleanup` 清理。
4. **套接字类型**Windows 中 `SOCKET` 类型是 `HANDLE`(句柄),而 Linux 中是 `int`文件描述符。Windows 的 `INVALID_SOCKET` 对应 Linux 的 `-1`
5. **关闭套接字**Windows 使用 `closesocket`Linux 使用 `close`
6. **错误处理**Windows 使用 `WSAGetLastError()` 获取错误码Linux 使用 `errno` 全局变量。
7. **函数返回值**:大部分函数返回值含义相同,但 Windows 中部分函数的返回类型可能不同(如 `recv` 返回 `int` 而非 `ssize_t`)。
### 4.5 习题
@@ -224,7 +238,7 @@ client:
3. **为何需要把 TCP/IP 协议栈分成 4 层或7层开放式回答。**
ARPANET 的研制经验表明,对于复杂的计算机网络协议,其结构应该是层次式的。分的好处:①层之间是独立的②灵活性好③结构上可以分隔开④易于实现和维护⑤能促进标准化工作。
ARPANET 的研制经验表明,对于复杂的计算机网络协议,其结构应该是层次式的。分的好处:①层与层之间是独立的②灵活性好③结构上可以分隔开④易于实现和维护⑤能促进标准化工作。
4. **客户端调用 connect 函数向服务器端发送请求。服务器端调用哪个函数后,客户端可以调用 connect 函数?**
@@ -232,8 +246,8 @@ client:
5. **什么时候创建连接请求等待队列?它有何种作用?与 accept 有什么关系?**
答:服务端调用 listen 函数accept函数正在处理客户端请求时 更多的客户端发来了请求连接的数据,此时,就需要创建连接请求等待队列。以便于在accept函数处理完手头的请求之后,按照正确的顺序处理后面正在排队的其他请求。与accept函数的关系accept函数受理连接请求等待队列中待处理的客户端连接请求
答:服务端调用 `listen` 函数时创建连接请求等待队列。作用:当多个客户端几乎同时向服务端发起连接请求时,服务端在调用 `accept` 函数处理当前请求的同时,后续的连接请求会进入该队列等待。与 `accept` 函数的关系:`accept` 函数从连接请求等待队列的队头取出一个连接请求进行处理,如果队列为空则 `accept` 函数会阻塞等待
6. **客户端中为何不需要调用 bind 函数分配地址?如果不调用 bind 函数那何时、如何向套接字分配IP地址和端口号**
答:在调用 connect 函数分配地址客户端IP地址和端口在调用 connect 函数时自动分配,无需调用标记的 bind 函数进行分配
答:客户端通常不需要显式调用 `bind` 函数分配地址。如果不调用 `bind` 函数,在调用 `connect` 函数时,操作系统会自动为客户端套接字分配 IP 地址(使用本机网络接口的 IP和端口号从临时端口范围中随机选择一个未使用的端口