mirror of
https://github.com/riba2534/TCP-IP-NetworkNote.git
synced 2026-05-05 06:52:11 +08:00
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:
@@ -10,7 +10,7 @@ TCP 的断开连接过程比建立连接更重要,因为连接过程中一般
|
||||
|
||||
#### 7.1.1 单方面断开连接带来的问题
|
||||
|
||||
Linux 和 Windows 的 closesocket 函数意味着完全断开连接。完全断开不仅指无法传输数据,而且也不能接收数据。因此在某些情况下,通信一方单方面的断开套接字连接,显得不太优雅。如图所示:
|
||||
Linux 的 close 函数和 Windows 的 closesocket 函数意味着完全断开连接。完全断开不仅指无法传输数据,而且也不能接收数据。因此在某些情况下,通信一方单方面的断开套接字连接,显得不太优雅。如图所示:
|
||||
|
||||

|
||||
|
||||
@@ -22,11 +22,11 @@ Linux 和 Windows 的 closesocket 函数意味着完全断开连接。完全断
|
||||
|
||||
两台主机通过套接字建立连接后进入可交换数据的状态,又称「流形成的状态」。也就是把建立套接字后可交换数据的状态看作一种流。
|
||||
|
||||
此处的流可以比作水流。水朝着一个方向流动,同样,在套接字的流中,数据也止呕能向一个方向流动。因此,为了进行双向通信,需要如图所示的两个流:
|
||||
此处的流可以比作水流。水朝着一个方向流动,同样,在套接字的流中,数据也只能向一个方向流动。因此,为了进行双向通信,需要如图所示的两个流:
|
||||
|
||||

|
||||
|
||||
一旦两台主机之间建立了套接字连接,每个主机就会拥有单独的输入流和输出流。当然,其中一个主机的输入流与另一个主机的输出流相连,而输出流则与另一个主机的输入流相连。另外,本章讨论的「优雅的断开连接方式」只断开其中 1 个流,而非同时断开两个流。Linux 和 Windows 的 closesocket 函数将同时断开这两个流,因此与「优雅」二字还有一段距离。
|
||||
一旦两台主机之间建立了套接字连接,每个主机就会拥有单独的输入流和输出流。当然,其中一个主机的输入流与另一个主机的输出流相连,而输出流则与另一个主机的输入流相连。另外,本章讨论的「优雅的断开连接方式」只断开其中 1 个流,而非同时断开两个流。Linux 的 close 函数和 Windows 的 closesocket 函数将同时断开这两个流,因此与「优雅」二字还有一段距离。
|
||||
|
||||
#### 7.1.3 针对优雅断开的 shutdown 函数
|
||||
|
||||
@@ -56,7 +56,7 @@ howto: 传递断开方式信息
|
||||
|
||||
> 一旦客户端连接到服务器,服务器将约定的文件传输给客户端,客户端收到后发送字符串「Thank you」给服务器端。
|
||||
|
||||
此处「Thank you」的传递是多余的,这只是用来模拟客户端断开连接前还有数据要传输的情况。此时程序的还嫌难度并不小,因为传输文件的服务器端只需连续传输文件数据即可,而客户端无法知道需要接收数据到何时。客户端也没办法无休止的调用输入函数,因为这有可能导致程序**阻塞**。
|
||||
此处「Thank you」的传递是多余的,这只是用来模拟客户端断开连接前还有数据要传输的情况。此时程序的编写难度并不小,因为传输文件的服务器端只需连续传输文件数据即可,而客户端无法知道需要接收数据到何时。客户端也没办法无休止的调用输入函数,因为这有可能导致程序**阻塞**。
|
||||
|
||||
> 是否可以让服务器和客户端约定一个代表文件尾的字符?
|
||||
|
||||
@@ -94,7 +94,25 @@ gcc file_server.c -o fserver
|
||||
|
||||
### 7.2 基于 Windows 的实现
|
||||
|
||||
暂略
|
||||
Windows 平台下的半关闭实现与 Linux 类似,同样使用 shutdown 函数。函数原型如下:
|
||||
|
||||
```c
|
||||
#include <winsock2.h>
|
||||
int shutdown(SOCKET s, int how);
|
||||
/*
|
||||
成功时返回 0,失败时返回 SOCKET_ERROR
|
||||
s: 需要断开的套接字句柄
|
||||
how: 传递断开方式信息
|
||||
*/
|
||||
```
|
||||
|
||||
Windows 下的 how 参数取值与 Linux 略有不同:
|
||||
|
||||
- `SD_RECEIVE` : 断开输入流(相当于 Linux 的 SHUT_RD)
|
||||
- `SD_SEND` : 断开输出流(相当于 Linux 的 SHUT_WR)
|
||||
- `SD_BOTH` : 同时断开 I/O 流(相当于 Linux 的 SHUT_RDWR)
|
||||
|
||||
使用方法与 Linux 版本基本一致,只需注意参数名称的差异即可。
|
||||
|
||||
### 7.3 习题
|
||||
|
||||
@@ -106,8 +124,14 @@ gcc file_server.c -o fserver
|
||||
|
||||
2. **Linux 中的 close 函数或 Windows 中的 closesocket 函数属于单方面断开连接的方法,有可能带来一些问题。什么是单方面断开连接?什么情形下会出现问题?**
|
||||
|
||||
答:单方面断开连接就是两台主机正在通信,其中一台主机关闭了所有连接,那么一台主机向另一台主机传输的数据可能会没有接收到而损毁。传输文件的服务器只需连续传输文件数据即可,而客户端不知道需要接收数据到何时。客户端也没有办法无休止的调用输入函数。现在需要一个 EOF 代表数据已经传输完毕,那么这时就需要半关闭,服务端把自己的输出流关了,这时客户端就知数据已经传输完毕,因为服务端的输入流还没关,客户端可以给服务器汇报,接收完毕。
|
||||
答:单方面断开连接是指通信的一方调用 close(Linux)或 closesocket(Windows)函数,同时关闭输入流和输出流。这会导致该主机既不能发送数据也不能接收数据。
|
||||
|
||||
问题出现的典型情形是:服务器向客户端传输文件,传输完成后需要接收客户端的确认信息(如「Thank you」)。如果服务器调用 close 函数发送 EOF,虽然客户端能知道文件传输完毕,但服务器也无法再接收客户端发送的确认信息了。解决方法是使用 shutdown 函数进行半关闭,只关闭输出流,保留输入流。
|
||||
|
||||
3. **什么是半关闭?针对输出流执行半关闭的主机处于何种状态?半关闭会导致对方主机接收什么消息?**
|
||||
|
||||
答:半关闭就是把输入流或者输出流关了。针对输出流执行半关闭的主机处于可以接收数据而不能发送数据。半关闭会导致对方主机接收一个 EOF 文件结束符。对方就知道你的数据已经传输完毕。
|
||||
答:半关闭是指只关闭套接字的输入流或输出流中的一种,而不是同时关闭两者。
|
||||
|
||||
针对输出流执行半关闭(即调用 `shutdown(sock, SHUT_WR)`)的主机处于:可以接收数据,但无法发送数据的状态。
|
||||
|
||||
半关闭会导致对方主机的接收函数返回 EOF(文件结束符),对方主机由此得知数据已传输完毕。
|
||||
|
||||
Reference in New Issue
Block a user