UNIX网络编程——客户/服务器程序设计示范(五)
TCP预先派生子进程服务器程序,传递描述符
对预先派生子进程服务器程序的最后一个修改版本是只让父进程调用accept,然后把所接受的已连接套接字“传递”给某个子进程。这么做绕过了为所有子进程的accept调用提供上锁保护的可能需求,不过需要从父进程到子进程的某种形式的描述符传递。这种技术会使代码多少有点复杂,因为父进程必须跟踪子进程的忙闲状态,以便给空闲子进程传递新的套接字。
在以前的预先派生子进程的例子中,父进程无需关心由哪个子进程接收一个客户连接。操作系统处理这个细节,给予某个子进程以首先调用accept的机会,或者给予某个子进程以所需的文件锁或互斥锁。
然而对于当前的预先派生子进程例子,我们必须为每个子进程维护一个信息结构以便管理。如下给出child的结构。
我们在该结构中存放相应子进程的进程ID,父进程中连接到该子进程的字节流管道描述符,子进程状态以及该子进程已处理客户的计数。我们的SIGINT信号处理函数将在终止程序前显示各个子进程的这个计数器值,以便观察全体客户请求在各个子进程之间的发布。
如下给出child_make函数。在调用fork之前先创建一个字节流管道。派生出子进程后,父进程关闭其中一个描述符(sockfd[1]),子进程关闭另一个描述符(sockfd[0])。父进程还把流管道的自身拥有端(sockfd[1])复制到标准错误输出,这样每个子进程就通过读写标准错误输出和父进程通信。父子进程之间的关系如图30-22所示。
#include "unp.h"
#include "child.h"
typedef struct {
pid_t child_pid; /* process ID */
int child_pipefd; /* parent's stream pipe to/from child */
int child_status; /* 0 = ready */
long child_count; /* # connections handled */
} Child; Child *cptr; /* array of Child structures; calloc'ed */ pid_t
child_make(int i, int listenfd, int addrlen)
{
int sockfd[2];
pid_t pid;
void child_main(int, int, int); Socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd); if ( (pid = Fork()) > 0) {
Close(sockfd[1]);
cptr[i].child_pid = pid;
cptr[i].child_pipefd = sockfd[0];
cptr[i].child_status = 0;
return(pid); /* parent */
} Dup2(sockfd[1], STDERR_FILENO); /* child's stream pipe to parent */
Close(sockfd[0]);
Close(sockfd[1]);
Close(listenfd); /* child does not need this open */
child_main(i, listenfd, addrlen); /* never returns */
}
void
child_main(int i, int listenfd, int addrlen)
{
char c;
int connfd;
ssize_t n;
void web_child(int); printf("child %ld starting\n", (long) getpid());
for ( ; ; ) {
if ( (n = Read_fd(STDERR_FILENO, &c, 1, &connfd)) == 0)
err_quit("read_fd returned 0");
if (connfd < 0)
err_quit("no descriptor from read_fd"); web_child(connfd); /* process request */
Close(connfd); Write(STDERR_FILENO, "", 1); /* tell parent we're ready again */
}
}

UNIX网络编程——客户/服务器程序设计示范(五)的更多相关文章
- UNIX网络编程——客户/服务器程序设计示范(总结)
(1)当系统负载较轻是,每来一个客户请求现场派生一个子进程为之服务的传统并发服务器程序模型就足够了.这个模型甚至可以与inetd结合使用,也就是inetd处理每个连接的接收.我们的其他意见是就重负荷运 ...
- UNIX网络编程——客户/服务器程序设计示范(八)
TCP预先创建线程服务器程序,主线程统一accept 最后一个使用线程的服务器程序设计示范是在程序启动阶段创建一个线程池之后只让主线程调用accept并把每个客户连接传递给池中某个可用线程. ...
- UNIX网络编程——客户/服务器程序设计示范(七)
TCP预先创建线程服务器程序,每个线程各自accept 前面讨论过预先派生一个子进程池快于为每个客户线程派生一个子进程.在支持线程的系统上,我们有理由预期在服务器启动阶段预先创建一个线程池以取 ...
- UNIX网络编程——客户/服务器程序设计示范(六)
TCP并发服务器程序,每个客户一个线程 前面讲述了,每个客户一个进程的服务器,或为每个客户现场fork一个子进程,或者预先派生一定数目的子进程.如果服务器主机支持线程,我们就可以改用线程以取代子进程. ...
- UNIX网络编程——客户/服务器程序设计示范(三)
TCP预先派生子进程服务器程序,accept无上锁保护 我们的第一个"增强"型服务器程序使用称为预先派生子进程的技术.使用该技术的服务器不像传统意义的并发服务器那样为每个客户现场派 ...
- UNIX网络编程——客户/服务器程序设计示范(二)
TCP并发服务器程序,每个客户一个子进程 传统上并发服务器调用fork派生一个子进程来处理每个客户.这使得服务器能够同时为多个客户服务,每个进程一个客户.客户数目的唯一限制是操作系统对以其名义 ...
- UNIX网络编程——客户/服务器程序设计示范(一)
下面给出的是客户程序用于测试我们的服务器程序的各个变体. #include "unp.h" #define MAXN 16384 /* max # bytes to request ...
- UNIX网络编程——客户/服务器程序设计示范(四)
TCP预先派生子进程服务器程序,accept使用线程上锁保护 我们使用线程上锁保护accept,因为这种方法不仅适用于同一进程内各线程之间的上锁,而且适用于不同进程之间的上锁. ...
- UNIX网络编程——客户/服务器心搏函数
阅读此博客时,可以参考以前的博客<<UNIX网络编程--socket的keep-alive>>和<<UNIX网络编程--套接字选项(心跳检测.绑定地址复用)> ...
随机推荐
- shell 报错:syntax error: unexpected end of file
有时执行脚本时会报错: [root@host1 shell]# sh -x test.sh + $'\r' : command not found test.: syntax error: unexp ...
- 【精解】EOS智能合约演练
EOS,智能合约,abi,wasm,cleos,eosiocpp,开发调试,钱包,账户,签名权限 热身 本文旨在针对EOS智能合约进行一个完整的实操演练,过程中深入熟悉掌握整个EOS智能合约的流程,过 ...
- 关于return的一些了解
写return是一种清晰的风格,可以防止一些意外的错误. 所以书上只说应该写,而不是必须写. 如果符合某个条件要退出的话,可以用return返回,否则可以不写这句代码的,当程序执行到"}&q ...
- 一口一口吃掉Hibernate(七)——继承映射
前几篇博文中讲到了常用的几种关联映射.其实hibernate中还有一种"省劲儿"的映射,那就是--"继承映射". 学了这么多的关系映射了,继承映射,从字面上也能 ...
- js操作符+和()
ECMA-262 描述了一组用于操作数据值的操作符,包括一元操作符.算数操作符逻辑操作符.关系操作符.赋值操作符.字符串操作符.对象操作符等.ECMAScript 操作符的与众不同之处在于,它们能够适 ...
- IOI2016Day2. Messy
题目链接:http://uoj.ac/problem/239 题目大意: 这是一道交互题,交互库维护了一个数据结构,可以存储n为二进制串,一开始你可以向空的数据结构中插入若干二进制串, 接下来这个数据 ...
- c++类的声明
就像函数的声明与定义分离一样,我们也可以仅声明类而暂时不定义类: class ClassName;//ClassName类的声明 这种声明有时被称作前向声明 对于一个类来说,我们创建它的对象之前该类必 ...
- reload(sys)后print失效问题解决
python版本: python2.7.6 #查看python默认编码格式 >>> import sys >>> print sys.getdefaultencod ...
- 【python标准库模块三】Os模块和Sys模块学习
Os模块 导入os模块 import os 获取当前工作目录 os.getcwd() 切换目录,跟linux中的cd一样 os.chdir("文件夹名") 递归生成文件夹 os.m ...
- ACM Primes
Write a program to read in a list of integers and determine whether or not each number is prime. A n ...