网站大量收购闲置独家精品文档,联系QQ:2885784924

第6章 网络服务器的设计模式.doc

  1. 1、本文档共27页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
第6章 网络服务器的设计模式

第6章 网络服务器的设计模式 6-1 概 述 第3章和第4章中讨论的是最基本的TCP服务器和UDP服务器:串行单用户服务器,本章将讨论服务多客户的网络服务器的设计模式。因为大多数网络服务器都是多进程或多线程应用,因此在讨论网络服务器的设计模式之前先介绍进程和线程的基本概念、编程接口以及程序设计方法。 6-2 多进程环境下的网络编程 6-2-1 进程的基本概念 在传统的多任务系统中,“进程”是一个很重要的概念,在系统中进程是程序执行的实体,它由一组机器指令()(fork)(1)fork()(2)(IPC)(Shared Memory)(Message Queue)(Pipe)6-2-2 多进程下的网络编程 Unix系统中派生新进程的唯一的方法是调用fork() #include unistd.h pid_t fork(void); fork()getpid获取父进程的进程ID。如果函数调用失败,则只在调用进程中返回-1。 fork函数的两个典型应用是: (1)(2)fork产生一个自己的副本()exec序列函数来代替自己去执行新程序。shell程序中常采用这种方式。 在网络服务器中,最常见的使用fork函数的工作方式是:父进程调用accept,当客户连接到达,accept成功返回时,调用fork派生一个子进程。然后,父进程关闭accept返回的已连接描述符,继续在监听描述符上调用accept等待下一个连接请求。而子进程则关闭父进程使用的监听描述符,使用accept返回的已连接描述符进行读写操作。上述过程可以用程序6-1来表示。 程序6-1 典型的调用fork的网络服务器程序结构。 /* 其他变量定义 */ int sockfd, connfd; pid_t pid; sockfd = socket(...); /* */ /* 设置服务器地址结构变量代码 */ bind(sockfd, ...); /* */ listen(sockfd, n); for (; ;) { connfd = accept(sockfd, ...); /* */ if ((pid= fork()) == 0) /* if*/ { close(sockfd); /* */ /* 通过connfd读写操作,任务处理 */ close(connfd); exit(0); }if (pid == -1) prinf(″fork() !\n″); close(connfd); /* */ } 下面我们来讨论为什么要在父进程中关闭已连接描述符,而在子进程中要关闭监听描述符,以及这样的做法不会造成不良后果的原因。 当一个描述符正被某一进程使用,又被另一进程打开时,并不是真的创建新的内存I结点,而只是将该描述符的引用数加1。调用fork()()fork()1。 在程序6-1中,父进程调用close关闭子进程使用的已连接插口时,它只是将描述符connfd的访问计数值减1。由于connfd的访问计数值仍然大于0,所以父进程中的这个close调用并没有使得内核启动TCP的四分组连接终止序列。因而不会影响子进程中对connfd的读写操作。同样子进程中的close调用也没有关闭父进程使用的监听描述符。 如果父进程不关闭accept返回的已连接插口,将会发生下列严重情况: (1)(2)close关闭其使用的已连接插口时,它的访问计数值只是由2变为1,连接并没有被关闭,资源仍被占用未释放。 如果子进程中不关闭父进程使用的监听描述符,则父进程调用close关闭监听描述符时也并没有真正关闭它,资源得不到释放。 在多进程应用中,如果一个进程确实要终止一个连接,但这个连接所对应的插口又被其他进程所使用,则必须通过shutdown而不是close来终止连接。关于shutdown的使用在第2章中已经详细讨论过。 在程序6-1中,当子进程处理完所有任务时,它调用exit()exit()()()(Zombie)wait()wait()#include sys/wait.h pid_t wait(int *stat) waitstat被用来返回子进程退出时的状态值(exit())wait将把结束的子进程完全释放,并获得其返回值。但是,如果子进程的执行没有结束,wait将阻塞调用它的父进程。解决办法是在信号SIGCHLD中断处理子程序中调用wait或waitpid。因为如果有子进程被中断,内核将给父进程发送SIGCHLD信号。 下面我们来看看调用wait函数的SIGCHLD信号中断处理子程序的程序结构,如程序6-2所示。 程序6-2 调用wait的SIGCHLD信号中断处理子程序。 void sigchld_handler(int

文档评论(0)

xcs88858 + 关注
实名认证
内容提供者

该用户很懒,什么也没介绍

版权声明书
用户编号:8130065136000003

1亿VIP精品文档

相关文档