完成了第 12 章 I/O 复用

This commit is contained in:
riba2534
2019-01-23 17:31:10 +08:00
parent 4931c03be6
commit 8b20f9f6f8
3 changed files with 374 additions and 2 deletions

View File

@@ -3263,7 +3263,7 @@ timeout: 调用 select 函数后,为防止陷入无限阻塞的状态,传递
1. 文件描述符的监视(检查)范围是?
2. 如何设定 select 函数的超时时间?
第一,文件描述符的监视范围和 select 的第一个参数有关。实际上select 函数要求通过第一个参数传递监视对象文件描述符的数量。因此,需要得到注册在 fd_set 变量中的文件描述符数。但每次信件文件描述符时,其值就会增加 1 ,故只需将最大的文件描述符值加 1 再传递给 select 函数即可。加 1 是因为文件描述符的值是从 0 开始的。
第一,文件描述符的监视范围和 select 的第一个参数有关。实际上select 函数要求通过第一个参数传递监视对象文件描述符的数量。因此,需要得到注册在 fd_set 变量中的文件描述符数。但每次新建文件描述符时,其值就会增加 1 ,故只需将最大的文件描述符值加 1 再传递给 select 函数即可。加 1 是因为文件描述符的值是从 0 开始的。
第二select 函数的超时时间与 select 函数的最后一个参数有关,其中 timeval 结构体定义如下:
@@ -3289,6 +3289,77 @@ select 返回正整数时,怎样获知哪些文件描述符发生了变化?
下面是一个 select 函数的例子:
- [select.c](https://github.com/riba2534/TCP-IP-NetworkNote/blob/master/ch12/select.c)
编译运行:
```shell
gcc select.c -o select
./select
```
结果:
![](https://s2.ax1x.com/2019/01/23/kAjgW6.png)
可以看出,如果运行后在标准输入流输入数据,就会在标准输出流输出数据,但是如果 5 秒没有输入数据,就提示超时。
#### 12.2.6 实现 I/O 复用服务器端
下面通过 select 函数实现 I/O 复用服务器端。下面是基于 I/O 复用的回声服务器端。
- [echo_selectserv.c](https://github.com/riba2534/TCP-IP-NetworkNote/blob/master/ch12/echo_selectserv.c)
编译运行:
```shell
gcc echo_selectserv.c -o selserv
./selserv 9190
```
结果:
![](https://s2.ax1x.com/2019/01/23/kEkV8H.png)
从图上可以看出,虽然只用了一个进程,但是却实现了可以和多个客户端进行通信,这都是利用了 select 的特点。
### 12.3 基于 Windows 的实现
暂略
### 12.4 习题
> 以下答案仅代表本人个人观点,可能不是正确答案。
1. **请解释复用技术的通用含义,并说明何为 I/O 复用。**
答:通用含义:在 1 个通信频道中传递多个数据信号的技术。IO复用就是进程预先告诉内核需要监视的IO条件使得内核一旦发现进程指定的一个或多个IO条件就绪就通过进程进程处理从而不会在单个IO上阻塞了。
参考文章:[Linux网络编程-IO复用技术](https://www.cnblogs.com/luoxn28/p/6220372.html)
2. **多进程并发服务器的缺点有哪些?如何在 I/O 复用服务器中弥补?**
答:多进程需要进行大量的运算和大量的内存空间。在 I/O 复用服务器中通过 select 函数监视文件描述符,通过判断变化的文件描述符,来得知变化的套接字是哪个,从而实时应答来自多个客户端的请求。
3. **复用服务器端需要 select 函数。下列关于 select 函数使用方法的描述错误的是?**
答:以下加粗的为正确的描述。
1. 调用 select 函数前需要集中 I/O 监视对象的文件描述符
2. **若已通过 select 函数注册为监视对象,则后续调用 select 函数时无需重复注册**
3. 复用服务器端同一时间只能服务于 1 个客户端,因此,需要服务的客户端接入服务器端后只能等待
4. **与多线程服务端不同,基于 select 的复用服务器只需要 1 个进程。因此,可以减少因创建多进程产生的服务器端的负担**
4. **select 函数的观察对象中应包含服务端套接字(监听套接字),那么应将其包含到哪一类监听对象集合?请说明原因**
答:应该包含到「是否存在待读取数据」,因为服务器端需要查看套接字中有没有可以读取的数据。
### 第 13 章 多种 I/O 函数
本章代码,在[TCP-IP-NetworkNote](https://github.com/riba2534/TCP-IP-NetworkNote)中可以找到。
### 13.1 send & recv 函数
## License