UNIX网络编程的回射服务器的改进步骤

本文深入探讨了TCP回射服务器的进化过程,从第一版本的各组成部分到处理SIGCHLD信号和引入waitpid的必要性。详细阐述了在服务器子进程终止时避免僵尸进程的方法,并解释了在特定情况下使用wait与waitpid的区别。同时,指出客户端阻塞问题及其解决方案——I/O复用技术的引入,以确保及时处理多个文件描述符。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

截至目前(UNP的5.12节)回射服务器的进化过程:

1.       5.2、5.3、5.4、5.5四节分别介绍了回射服务器的第一个版本的各个组成部分。

2.       5.7节讲到正常终止时,讲到了server child结束时,并没有被父进程清理而留下了僵尸进程。5.8节开始讲POSIX信号处理,讲述自定义函数signal。

3.       5.9节开始讲处理SIGCHLD信号,用wait写了一个简单的信号处理函数。此时,wait会的执行会中断server parent的系统调用accept的执行,引出了“处理被中断的系统调用”,因此也改写了accept的实现。

4.       又引入了waitpid,但是为什么会引入waitpid呢?

Wait是包装过的waitpid,是waitpid的简化版本,wait的内部实现还是通过调用waitpid来实现的。因此waitpid提供了比wait更多控制功能的选项。

为了说明二者的区别改写了客户端的代码,改成“和服务器建立5个连接”这种情况下,wait不足以保证不产生僵死进程,因为信号的不排队性(UNIX信号一般是不排队的)。此时要调用waitpid来循环处理这个信号,而且要指定WNOHANG选项(他告知waitpid在有尚未终止的子进程在运行时不要阻塞)。这时,可能会说“循环调用wait,不也行吗”,其实,在这个地方循环调用wait是可以的,因为这是巧合:本例中,信号几乎同时到达,wait循环处理完了这些僵死进程,之后没有在运行的子进程了,所以wait退出了,没有阻塞。这个条件“没有在运行的子进程了”是造成巧合的原因。

5.       至此,我们完成了TCP回射服务器的最终版本(包括figure 5.11的SIGCHLD信号处理函数)。 

6.       回射服务器的客户端版本还存在问题(问题就是这么多)问题发生的背景:服务器的子进程被终止了,此时,客户端阻塞在fgets出并收不到server child因终止而发过来的FIN信号(事实上,收到了只是阻塞了没有处理);客户端输入了数据,调用writen,接着客户端把输入的数据发送给服务器(这个动作时被允许的因为此时的状态时由服务器端主动关闭的半关闭状态);服务器收到数据后,发现该连接已关闭而给客户端发送了RST;客户端是看不到这个RST的,因为他在调用writen后立即调用readline,读到了刚才收到的FIN而返回0,所以提示:server terminated prematurely。

其实我们上述的讨论基于程序运行的时序,上述是readline发生在RST前,如果在其后的话则返回connection reset by peer(对方复位连接)的错误。

本例的问题是:the sever child发送个client的FIN没有被及时的处理(因为客户端被阻塞到fgets函数),客户端有两个文件描述字:套接口和用户的输入,用户不应该阻塞到一个而不顾及另一个,要都顾及这该怎么办?这就引出了I/O multiplexing(I/O 复用)的select和poll函数。他们可以同时监视多个描述字保证及时处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值