前言
在之前的文章中,我具体实现了一个并发回射服务器并给它加载了僵尸子进程的自动清理信号机制。在正常情况下,它已经可以很好地工作了,但它能否合理应对一些特殊情况呢?
问题发现
先来看看当服务器的客户子进程突然崩溃的情况。
1. 终端启动上篇文章中已经实现了的并发服务器
2. 在另一个终端中启动上篇文章中已经实现了的客户端并执行回射测试:
可以看到运行良好。
3. 找到服务器子进程的ID,然后kill掉它:
4. 再回到客户端执行回射,但这一次我们得到这样的结果:
表面上看,客户端的响应也是正常的,但在实际应用中却大错特错了。
因为当服务器的客户子进程结束,这边客户端应该立马收到连接失效的信息,而不是还一厢情愿 地往里面输数据白白浪费时间。
在《UNIX网络编程中》作者是这样描述这种情况的“ 当FIN分节到达时,客户正阻塞在fgets上。客户实际是应对两个描述符:套接字分节和用户输入。程序不能阻塞于这两个描述符中的某一个上,而是应该阻塞于任何一个上 ”。那么如何做到“ 阻塞于任何一个上 "?
这就引出了本文要讨论的重要概念:IO复用。
重要概念:IO复用
在程序有多个IO( 如套接字描述符和用户输入 )的情况下,内核一旦发现某个或多个IO条件就绪,就通知进程。这个能力就叫做IO复用。
具体实现
请看接下来的两篇文章:《IO复用之select实现》或《IO复用之poll实现》。