mirror of
https://github.com/riba2534/TCP-IP-NetworkNote.git
synced 2026-05-05 06:03:10 +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:
@@ -24,7 +24,7 @@ I/O 复用技术可以解决这个问题。
|
||||
|
||||

|
||||
|
||||
上图是一个纸杯电话系统,为了使得三人同时通话,说话时要同事对着两个纸杯,接听时也需要耳朵同时对准两个纸杯。为了完成 3 人通话,可以进行如下图的改进:
|
||||
上图是一个纸杯电话系统,为了使得三人同时通话,说话时要同时对着两个纸杯,接听时也需要耳朵同时对准两个纸杯。为了完成 3 人通话,可以进行如下图的改进:
|
||||
|
||||

|
||||
|
||||
@@ -107,7 +107,7 @@ readset: 将所有关注「是否存在待读取数据」的文件描述符注
|
||||
writeset: 将所有关注「是否可传输无阻塞数据」的文件描述符注册到 fd_set 型变量,并传递其地址值。
|
||||
exceptset: 将所有关注「是否发生异常」的文件描述符注册到 fd_set 型变量,并传递其地址值。
|
||||
timeout: 调用 select 函数后,为防止陷入无限阻塞的状态,传递超时(time-out)信息
|
||||
返回值: 发生错误时返回 -1,超时时返回0,。因发生关注的时间返回时,返回大于0的值,该值是发生事件的文件描述符数。
|
||||
返回值: 发生错误时返回 -1,超时时返回 0。因发生关注的事件返回时,返回大于 0 的值,该值是发生事件的文件描述符数。
|
||||
*/
|
||||
```
|
||||
|
||||
@@ -128,7 +128,7 @@ struct timeval
|
||||
};
|
||||
```
|
||||
|
||||
本来 select 函数只有在监视文件描述符发生变化时才返回。如果未发生变化,就会进入阻塞状态。指定超时时间就是为了防止这种情况的发生。通过上述结构体变量,将秒数填入 tv_sec 的成员,将微妙数填入 tv_usec 的成员,然后将结构体的地址值传递到 select 函数的最后一个参数。此时,即使文件描述符未发生变化,只要过了指定时间,也可以从函数中返回。不过这种情况下, select 函数返回 0 。因此,可以通过返回值了解原因。如果不想设置超时,则传递 NULL 参数。
|
||||
本来 select 函数只有在监视文件描述符发生变化时才返回。如果未发生变化,就会进入阻塞状态。指定超时时间就是为了防止这种情况的发生。通过上述结构体变量,将秒数填入 tv_sec 的成员,将微秒数填入 tv_usec 的成员,然后将结构体的地址值传递到 select 函数的最后一个参数。此时,即使文件描述符未发生变化,只要过了指定时间,也可以从函数中返回。不过这种情况下,select 函数返回 0。因此,可以通过返回值了解原因。如果不想设置超时,则传递 NULL 参数。
|
||||
|
||||
#### 12.2.4 调用 select 函数查看结果
|
||||
|
||||
@@ -186,7 +186,7 @@ gcc echo_selectserv.c -o selserv
|
||||
|
||||
1. **请解释复用技术的通用含义,并说明何为 I/O 复用。**
|
||||
|
||||
答:通用含义:在 1 个通信频道中传递多个数据(信号)的技术。IO复用就是进程预先告诉内核需要监视的IO条件,使得内核一旦发现进程指定的一个或多个IO条件就绪,就通过进程进程处理,从而不会在单个IO上阻塞了。
|
||||
答:通用含义:在 1 个通信频道中传递多个数据(信号)的技术。I/O 复用是指进程预先告诉内核需要监视的 I/O 条件,使得内核一旦发现进程指定的一个或多个 I/O 条件就绪(例如套接字变为可读或可写),就通知进程进行处理,从而进程不会在单个 I/O 操作上阻塞。
|
||||
|
||||
参考文章:[Linux网络编程-IO复用技术](https://www.cnblogs.com/luoxn28/p/6220372.html)
|
||||
|
||||
@@ -194,15 +194,15 @@ gcc echo_selectserv.c -o selserv
|
||||
|
||||
答:多进程需要进行大量的运算和大量的内存空间。在 I/O 复用服务器中通过 select 函数监视文件描述符,通过判断变化的文件描述符,来得知变化的套接字是哪个,从而实时应答来自多个客户端的请求。
|
||||
|
||||
3. **复用服务器端需要 select 函数。下列关于 select 函数使用方法的描述错误的是?**
|
||||
3. **复用服务器端需要 select 函数。下列关于 select 函数使用方法的描述错误的是?**
|
||||
|
||||
答:以下加粗的为正确的描述。
|
||||
答:错误的描述是 2 和 3。说明如下:
|
||||
|
||||
1. 调用 select 函数前需要集中 I/O 监视对象的文件描述符
|
||||
2. **若已通过 select 函数注册为监视对象,则后续调用 select 函数时无需重复注册**
|
||||
3. 复用服务器端同一时间只能服务于 1 个客户端,因此,需要服务的客户端接入服务器端后只能等待
|
||||
4. **与多线程服务端不同,基于 select 的复用服务器只需要 1 个进程。因此,可以减少因创建多进程产生的服务器端的负担**。
|
||||
- 描述 1 正确:调用 select 函数前需要集中 I/O 监视对象的文件描述符。
|
||||
- 描述 2 错误:**每次调用 select 函数时都需要重新注册监视对象**,因为 select 函数调用后,fd_set 变量会被修改,只保留发生变化的文件描述符位为 1。
|
||||
- 描述 3 错误:**复用服务器端可以同时服务于多个客户端**,这正是 I/O 复用的核心优势——通过 select 函数同时监视多个套接字,哪个就绪就处理哪个。
|
||||
- 描述 4 正确:与多进程/多线程服务端不同,基于 select 的复用服务器只需要 1 个进程,可以减少因创建多进程产生的服务器端的负担。
|
||||
|
||||
4. **select 函数的观察对象中应包含服务端套接字(监听套接字),那么应将其包含到哪一类监听对象集合?请说明原因**。
|
||||
|
||||
答:应该包含到「是否存在待读取数据」,因为服务器端需要查看套接字中有没有可以读取的数据。
|
||||
答:应该包含到「是否存在待读取数据」(即 readset)集合中。原因是:服务端套接字(监听套接字)的作用是监听客户端的连接请求,当有新的客户端发起连接时,监听套接字变为「可读」状态,此时 accept 函数不会阻塞,可以成功完成连接。因此需要监视监听套接字是否可读,以得知是否有新的连接请求到来。
|
||||
|
||||
Reference in New Issue
Block a user