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

来源:互联网 发布:excel成绩分析软件 编辑:程序博客网 时间:2024/04/30 14:17

截至目前(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函数。他们可以同时监视多个描述字保证及时处理。

原创粉丝点击