mirror of
https://github.com/riba2534/TCP-IP-NetworkNote.git
synced 2026-07-05 20:36:03 +08:00
docs: 全面校对全部章节文档与示例代码
通过多智能体工作流对 19 章笔记(README.md)与 96 个 .c 示例代码做深度 审查与对抗性验证,修复 317 处确认问题,涵盖: 技术正确性: - 修复缓冲区溢出:echo_mpserv.c / echo_storeserv.c 等的 read(buf, BUFSIZ) 改为 BUF_SIZE(buf 仅 30 字节,BUFSIZ 远大于此) - 修复 open() 缺少 mode 参数:low_open.c / fd_seri.c / desto.c 等 O_CREAT 调用补 0644(原导致 low_read 链路失败) - 修复 feof 循环 off-by-one:news_sender.c / echo_stdserv.c 改用 fgets 返回值判断 - 修复线程竞态:chat_server.c / webserv_linux.c 的 &clnt_sock 栈地址 传子线程改为 malloc 分配 + free - 修复索引混淆:char_EPLTserv.c 错用 clnt_sock 查找改为 ep_events[i].data.fd - 修复格式化符:thread4.c 的 sizeof 用 %d 改为 %zu - 修正习题答案:ch01 fd 序号、ch13 MSG_OOB 加粗项、ch09 Nagle 等 文档规范: - 统一术语:IPv4/IPv6、接收(receive)/连接(connection) - 修正错别字:occured→occurred、cooffee→coffee、Usgae→Usage、 eerror→error、proess→process 等 - 修复病句、补全习题答案解释 - GitHub 绝对 URL 改为相对路径,统一项目引用规范 - 同步根 README.md(前言 + 19 章合并) 另:重命名 ch10/remove_zomebie.c → remove_zombie.c(修正拼写) 所有 .c 文件经 gcc 编译验证通过(ch17 epoll 文件因 macOS 无 sys/epoll.h 跳过,已人工复核)。
This commit is contained in:
@@ -22,7 +22,7 @@ write(sock, message, strlen(message));
|
||||
str_len = read(sock, message, BUF_SIZE - 1);
|
||||
```
|
||||
|
||||
二者都在循环调用 read 和 write 函数。实际上之前的回声客户端将 100% 接收字节传输的数据,只不过接收数据时的单位有些问题。扩展客户端代码回顾范围,下面是客户端的代码:
|
||||
二者都在循环调用 read 和 write 函数。实际上之前的回声客户端会接收服务器传输的全部数据,只不过接收数据时的单位有些问题。扩展客户端代码回顾范围,下面是客户端的代码:
|
||||
|
||||
```c
|
||||
while (1)
|
||||
@@ -48,7 +48,7 @@ while (1)
|
||||
|
||||
- [echo_client2.c](https://github.com/riba2534/TCP-IP-NetworkNote/blob/master/ch05/echo_client2.c)
|
||||
|
||||
这样修改为了接收所有传输数据而循环调用 read 函数。测试及运行结果可参考第四章。
|
||||
这样修改后,客户端为接收所有传输数据而循环调用 read 函数。测试及运行结果可参考第四章。
|
||||
|
||||
#### 5.1.3 如果问题不在于回声客户端:定义应用层协议
|
||||
|
||||
@@ -57,7 +57,7 @@ while (1)
|
||||
现在写一个小程序来体验应用层协议的定义过程。要求:
|
||||
|
||||
1. 服务器从客户端获得多个数组和运算符信息。
|
||||
2. 服务器接收到数字后对齐进行加减乘运算,然后把结果传回客户端。
|
||||
2. 服务器接收到数字后对其进行加减乘运算,然后把结果传回客户端。
|
||||
|
||||
例:
|
||||
|
||||
@@ -114,7 +114,7 @@ gcc op_server.c -o opserver
|
||||
|
||||
#### 5.2.1 TCP 套接字中的 I/O 缓冲
|
||||
|
||||
TCP 套接字的数据收发无边界。服务器即使调用 1 次 write 函数传输 40 字节的数据,客户端也有可能通过 4 次 read 函数调用每次读取 10 字节。但此处也有一些疑问,服务器一次性传输了 40 字节,而客户端竟然可以缓慢的分批接收。客户端接收 10 字节后,剩下的 30 字节在何处等候呢?
|
||||
TCP 套接字的数据收发无边界。服务器即使调用 1 次 write 函数传输 40 字节的数据,客户端也有可能通过 4 次 read 函数调用每次读取 10 字节。但此处也有一些疑问,服务器一次性传输了 40 字节,而客户端竟然可以缓慢地分批接收。客户端接收 10 字节后,剩下的 30 字节在何处等候呢?
|
||||
|
||||
实际上,write 函数调用后并非立即传输数据,read 函数调用后也并非马上接收数据。如图所示,write 函数调用瞬间,数据将移至输出缓冲;read 函数调用瞬间,从输入缓冲读取数据。
|
||||
|
||||
@@ -140,7 +140,7 @@ I/O 缓冲特性可以整理如下:
|
||||
|
||||
数据收发也是如此,因此 TCP 中不会因为缓冲溢出而丢失数据。
|
||||
|
||||
**write 函数在数据传输完成时返回。**
|
||||
**write 函数在数据成功移入输出缓冲时返回(并非等到对端接收完毕)。**
|
||||
|
||||
#### 5.2.2 TCP 内部工作原理 1:与对方套接字的连接
|
||||
|
||||
@@ -180,11 +180,11 @@ TCP 在实际通信中也会经过三次对话过程,因此,该过程又被
|
||||
|
||||
> 刚才传输的 SEQ 为 1000 的数据包接收无误,现在请传递 SEQ 为 1001 的数据包。
|
||||
|
||||
对于主机 A 首次传输的数据包的确认消息(ACK 1001)和为主机 B 传输数据做准备的同步消息(SEQ 2000)捆绑发送。因此,此种类消息又称为 SYN+ACK。
|
||||
对于主机 A 首次传输的数据包的确认消息(ACK 1001)和为主机 B 传输数据做准备的同步消息(SEQ 2000)捆绑发送。因此,此类消息又称为 SYN+ACK。
|
||||
|
||||
收发数据前向数据包分配序号,并向对方通报此序号,这都是为了防止数据丢失做的准备。通过向数据包分配序号并确认,可以在数据包丢失时马上查看并重传丢失的数据包。因此 TCP 可以保证可靠的数据传输。
|
||||
|
||||
通过这三个过程,这样主机 A 和主机 B 就确认了彼此已经准备就绪。
|
||||
通过这三个过程,主机 A 和主机 B 就确认了彼此已经准备就绪。
|
||||
|
||||
#### 5.2.3 TCP 内部工作原理 2:与对方主机的数据交换
|
||||
|
||||
@@ -217,7 +217,7 @@ TCP 套接字的结束过程也非常优雅。如果对方还有数据需要传
|
||||
|
||||

|
||||
|
||||
图中数据包内的 FIN 表示断开连接。也就是说,双方各发送 1 次 FIN 消息后断开连接。此过程经历 4 个阶段,因此又称四次握手(Four-way handshaking)。SEQ 和 ACK 的含义与之前讲解的内容一致,省略。图中,主机 A 传递了两次 ACK 5001,也许这里会有困惑。其实,第二次 FIN 数据包中的 ACK 5001 只是因为接收了 ACK 消息后未接收到的数据重传的。
|
||||
图中数据包内的 FIN 表示断开连接。也就是说,双方各发送 1 次 FIN 消息后断开连接。此过程经历 4 个阶段,因此又称四次握手(Four-way handshaking)。SEQ 和 ACK 的含义与之前讲解的内容一致,省略。图中,主机 A 传递了两次 ACK 5001,也许这里会有困惑。其实,图中第二次出现的 ACK 5001 是重传确认:若主机 B 未收到主机 A 第一次发出的 ACK,B 会重传 FIN,主机 A 收到后再次发送 ACK 5001 予以确认。
|
||||
|
||||
### 5.3 基于 Windows 的实现
|
||||
|
||||
|
||||
Reference in New Issue
Block a user