迭代服务器与并发服务器

2014-07-01 20:28:10   最后更新: 2014-07-01 20:28:10   访问数量:572




只有一个进程的服务器是最简单的实现,被称为“迭代服务器”,但是一般的我们并不希望整个服务器被单个用户长期占用,而是希望同时服务多个用户,因此就需要并发服务器

UNIX中编写并发服务器程序最简单的方法就是fork一个子进程来服务每个客户

下面提供了并发服务器程序的框架:

pid_t pid; int listenfd, connfd; listenfd = socket ( ... ); bind (listenfd, ... ); listen (listenfd, LISTENQ); for ( ; ; ) { connfd = accept (listenfd, ... ); if ( (pid = fork()) == 0 ) { close (listenfd); doit (connfd); close (connfd); exit (0); } close (connfd); }

 

当一个连接建立时,accept 返回,服务器接着调用 fork(关于 fork 函数的使用可以参看:创建子进程 -- fork、vfork,fork 与竞争条件exec 函数 -- execl、execv、execle、execve、execlp、execvp),然后由子进程服务客户(通过已连接套接字 connfd),父进程则等待另一个连接(通过监听套接字 listenfd),既然新的客户由子进程提供服务,父进程就关闭已连接套接字

上述代码中的 doit 函数即是我们假定的客户所需的所有操作,当该函数返回时,我们调用close关闭了已连接套接字,事实上,在调用 exit 函数时,系统会自动进行进程终止处理,其中就包括所有内核打开的描述符的关闭工作,因此此时是否显式调用 close 函数并没有什么影响

 

需要注意的是,父进程 close connfd 并不会终止与客户的连接,因为每个文件或套接字都有一个引用计数,引用计数在文件表项中维护,他是当前打开这的引用该文件或套接字的描述符的个数,每次调用 close 函数,会将相应的描述符的引用计数减一,只有在引用计数被减为零时才会关闭该文件或套接字,fork 后由于子进程复制了父进程的全部描述符,所以相应的引用计数就会加倍,因此父进程进行对 connfd 的 close 并不会造成子进程中的连接被关闭

 

accept 函数返回已连接套接字,使用这个套接字就可以跨连接读写数据了,之后父进程 fork 出子进程,此时父进程与子进程共享该连接以及监听套接字,紧接着,父进程关闭 connfd,子进程关闭 listenfd,此时,只有子进程与客户维持连接状态,而父进程则可以使用监听套接字 listenfd 再次调用 accept 来处理下一个客户连接

 






读书笔记      技术帖      tcp      socket      龙潭书斋      套接字      服务器     


京ICP备15018585号