⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 48.htm

📁 unix高级编程原吗
💻 HTM
字号:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>CTerm非常精华下载</title>
</head>
<body bgcolor="#FFFFFF">
<table border="0" width="100%" cellspacing="0" cellpadding="0" height="577">
<tr><td width="32%" rowspan="3" height="123"><img src="DDl_back.jpg" width="300" height="129" alt="DDl_back.jpg"></td><td width="30%" background="DDl_back2.jpg" height="35"><p align="center"><a href="http://apue.dhs.org"><font face="黑体"><big><big>123</big></big></font></a></td></tr>
<tr>
<td width="68%" background="DDl_back2.jpg" height="44"><big><big><font face="黑体"><p align="center">               ● UNIX网络编程                       (BM: clown)                </font></big></big></td></tr>
<tr>
<td width="68%" height="44" bgcolor="#000000"><font face="黑体"><big><big><p   align="center"></big></big><a href="http://cterm.163.net"><img src="banner.gif" width="400" height="60" alt="banner.gif"border="0"></a></font></td>
</tr>
<tr><td width="100%" colspan="2" height="100" align="center" valign="top"><br><p align="center">[<a href="index.htm">回到开始</a>][<a href="19.htm">上一层</a>][<a href="49.htm">下一篇</a>]
<hr><p align="left"><small>  <br>

Linux网络编程--9. 服务器模型 <br>

http://linuxc.51.net 作者:hoyt (2001-05-08 11:23:59) <br>

    学习过《软件工程》吧.软件工程可是每一个程序员"必修"的课程啊.如果你没有学 <br>

习过, 建议你去看一看. 在这一章里面,我们一起来从软件工程的角度学习网络编程的思 <br>

想.在我们写程序之前, 我们都应该从软件工程的角度规划好我们的软件,这样我们开发 <br>

软件的效率才会高. 在网络程序里面,一般的来说都是许多客户机对应一个服务器.为了 <br>

处理客户机的请求, 对服务端的程序就提出了特殊的要求.我们学习一下目前最常用的服 <br>

务器模型. <br>

循环服务器:循环服务器在同一个时刻只可以响应一个客户端的请求 <br>

并发服务器:并发服务器在同一个时刻可以响应多个客户端的请求 <br>

9.1 循环服务器:UDP服务器 <br>

UDP循环服务器的实现非常简单:UDP服务器每次从套接字上读取一个客户端的请求,处理 <br>

, 然后将结果返回给客户机. <br>

可以用下面的算法来实现. <br>

   socket(...); <br>

   bind(...); <br>

   while(1) <br>

    { <br>

         recvfrom(...); <br>

         process(...); <br>

         sendto(...); <br>

   } <br>

   } <br>

因为UDP是非面向连接的,没有一个客户端可以老是占住服务端. 只要处理过程不是死循 <br>

环, 服务器对于每一个客户机的请求总是能够满足. <br>

9.2 循环服务器:TCP服务器 <br>

TCP循环服务器的实现也不难:TCP服务器接受一个客户端的连接,然后处理,完成了这个客 <br>

户的所有请求后,断开连接. <br>

算法如下: <br>

        socket(...); <br>

        bind(...); <br>

        listen(...); <br>

        while(1) <br>

        { <br>

                accept(...); <br>

                while(1) <br>

                { <br>

                        read(...); <br>

                        process(...); <br>

                        write(...); <br>

                } <br>

                close(...); <br>

        } <br>

TCP循环服务器一次只能处理一个客户端的请求.只有在这个客户的所有请求都满足后, <br>

服务器才可以继续后面的请求.这样如果有一个客户端占住服务器不放时,其它的客户机 <br>



都不能工作了.因此,TCP服务器一般很少用循环服务器模型的. <br>

9.3 并发服务器:TCP服务器 <br>

为了弥补循环TCP服务器的缺陷,人们又想出了并发服务器的模型. 并发服务器的思想是 <br>

每一个客户机的请求并不由服务器直接处理,而是服务器创建一个 子进程来处理. <br>

算法如下: <br>

  socket(...); <br>

  bind(...); <br>

  listen(...); <br>

  while(1) <br>

  { <br>

        accept(...); <br>

        if(fork(..)==0) <br>

          { <br>

              while(1) <br>

               { <br>

                read(...); <br>

                process(...); <br>

                write(...); <br>

               } <br>

           close(...); <br>

           exit(...); <br>

          } <br>

          } <br>

        close(...); <br>

  } <br>

TCP并发服务器可以解决TCP循环服务器客户机独占服务器的情况. 不过也同时带来了一 <br>

个不小的问题.为了响应客户机的请求,服务器要创建子进程来处理. 而创建子进程是一 <br>

种非常消耗资源的操作. <br>

9.4 并发服务器:多路复用I/O <br>

为了解决创建子进程带来的系统资源消耗,人们又想出了多路复用I/O模型. <br>

首先介绍一个函数select <br>

 int select(int nfds,fd_set *readfds,fd_set *writefds, <br>

                fd_set *except fds,struct timeval *timeout) <br>

 void FD_SET(int fd,fd_set *fdset) <br>

 void FD_CLR(int fd,fd_set *fdset) <br>

 void FD_ZERO(fd_set *fdset) <br>

 int FD_ISSET(int fd,fd_set *fdset) <br>

一般的来说当我们在向文件读写时,进程有可能在读写出阻塞,直到一定的条件满足. 比 <br>

如我们从一个套接字读数据时,可能缓冲区里面没有数据可读(通信的对方还没有 发送数 <br>

据过来),这个时候我们的读调用就会等待(阻塞)直到有数据可读.如果我们不 希望阻塞 <br>

,我们的一个选择是用select系统调用. 只要我们设置好select的各个参数,那么当文件 <br>

可以读写的时候select回"通知"我们 说可以读写了. readfds所有要读的文件文件描述 <br>

符的集合 <br>

writefds所有要的写文件文件描述符的集合 <br>

exceptfds其他的服要向我们通知的文件描述符 <br>



timeout超时设置. <br>

nfds所有我们监控的文件描述符中最大的那一个加1 <br>

在我们调用select时进程会一直阻塞直到以下的一种情况发生. 1)有文件可以读.2)有文 <br>

件可以写.3)超时所设置的时间到. <br>

为了设置文件描述符我们要使用几个宏. FD_SET将fd加入到fdset <br>

FD_CLR将fd从fdset里面清除 <br>

FD_ZERO从fdset中清除所有的文件描述符 <br>

FD_ISSET判断fd是否在fdset集合中 <br>

使用select的一个例子 <br>

int use_select(int *readfd,int n) <br>

{ <br>

   fd_set my_readfd; <br>

   int maxfd; <br>

   int i; <br>

   maxfd=readfd[0]; <br>

   for(i=1;i    if(readfd[i]>maxfd) maxfd=readfd[i]; <br>

   while(1) <br>

   { <br>

        /*   将所有的文件描述符加入   */ <br>

        FD_ZERO(&my_readfd); <br>

        for(i=0;i            FD_SET(readfd[i],*my_readfd); <br>

        /*     进程阻塞                 */ <br>



        select(maxfd+1,& my_readfd,NULL,NULL,NULL); <br>

        /*        有东西可以读了       */ <br>

        for(i=0;i          if(FD_ISSET(readfd[i],&my_readfd)) <br>

              { <br>

                  /* 原来是我可以读了  */ <br>

                        we_read(readfd[i]); <br>

              } <br>

   } <br>

} <br>

使用select后我们的服务器程序就变成了. <br>

        初始话(socket,bind,listen); <br>

    while(1) <br>

        { <br>

        设置监听读写文件描述符(FD_*); <br>

        调用select; <br>

        如果是倾听套接字就绪,说明一个新的连接请求建立 <br>

             { <br>

                建立连接(accept); <br>

                加入到监听文件描述符中去; <br>

             } <br>

       否则说明是一个已经连接过的描述符 <br>

                { <br>



                    进行操作(read或者write); <br>

                 } <br>

        } <br>

多路复用I/O可以解决资源限制的问题.着模型实际上是将UDP循环模型用在了TCP上面. <br>

这也就带来了一些问题.如由于服务器依次处理客户的请求,所以可能会导致有的客户 会 <br>

等待很久. <br>

9.5 并发服务器:UDP服务器 <br>

人们把并发的概念用于UDP就得到了并发UDP服务器模型. 并发UDP服务器模型其实是简单 <br>

的.和并发的TCP服务器模型一样是创建一个子进程来处理的 算法和并发的TCP模型一样 <br>

. <br>

除非服务器在处理客户端的请求所用的时间比较长以外,人们实际上很少用这种模型. <br>

9.6 一个并发TCP服务器实例 <br>

#include <br>

#include <br>

#include <br>

#include <br>

#include <br>

#define MY_PORT         8888 <br>

int main(int argc ,char **argv) <br>

{ <br>

 int listen_fd,accept_fd; <br>

 struct sockaddr_in     client_addr; <br>



 int n; <br>

 if((listen_fd=socket(AF_INET,SOCK_STREAM,0))<0) <br>

  { <br>

        printf("Socket Error:%s\n\a",strerror(errno)); <br>

        exit(1); <br>

  } <br>

 bzero(&client_addr,sizeof(struct sockaddr_in)); <br>

 client_addr.sin_family=AF_INET; <br>

 client_addr.sin_port=htons(MY_PORT); <br>

 client_addr.sin_addr.s_addr=htonl(INADDR_ANY); <br>

 n=1; <br>

 /* 如果服务器终止后,服务器可以第二次快速启动而不用等待一段时间  */ <br>

 setsockopt(listen_fd,SOL_SOCKET,SO_REUSEADDR,&n,sizeof(int)); <br>

 if(bind(listen_fd,(struct sockaddr *)&client_addr,sizeof(client_addr))<0) <br>

  { <br>

        printf("Bind Error:%s\n\a",strerror(errno)); <br>

        exit(1); <br>

  } <br>

  listen(listen_fd,5); <br>

  while(1) <br>

  { <br>

   accept_fd=accept(listen_fd,NULL,NULL); <br>



   if((accept_fd<0)&&(errno==EINTR)) <br>

          continue; <br>

   else if(accept_fd<0) <br>

    { <br>

        printf("Accept Error:%s\n\a",strerror(errno)); <br>

        continue; <br>

    } <br>

  if((n=fork())==0) <br>

   { <br>

        /* 子进程处理客户端的连接 */ <br>

        char buffer[1024]; <br>

        close(listen_fd); <br>

        n=read(accept_fd,buffer,1024); <br>

        write(accept_fd,buffer,n); <br>

        close(accept_fd); <br>

        exit(0); <br>

   } <br>

   else if(n<0) <br>

        printf("Fork Error:%s\n\a",strerror(errno)); <br>

   close(accept_fd); <br>

  } <br>

} <br>



你可以用我们前面写客户端程序来调试着程序,或者是用来telnet调试 <br>

---------------------------------------------------------------------------- <br>

---- <br>

相关文章 关键词 <br>

Linux网络编程--8. 套接字选项 (2001-05-08 11:23:24) <br>

Linux网络编程--7. TCP/IP协议 (2001-05-08 11:22:40) <br>

Linux网络编程--6. 高级套接字函数 (2001-05-08 11:22:09) <br>

Linux网络编程--5. 用户数据报发送 (2001-05-08 11:21:31) <br>

Linux网络编程--4. 完整的读写函数 (2001-05-08 11:20:52) <br>

Linux网络编程--3. 服务器和客户机的信息函数 (2001-05-08 11:20:14) <br>

Linux网络编程--2. 初等网络函数介绍(TCP) (2001-05-08 11:19:34) <br>

Linux网络编程--1. Linux网络知识介绍 (2001-05-08 11:16:55) <br>

樊强制作 欢迎分享 2001 <br>

  <br>

</small><hr>
<p align="center">[<a href="index.htm">回到开始</a>][<a href="19.htm">上一层</a>][<a href="49.htm">下一篇</a>]
<p align="center"><a href="http://cterm.163.net">欢迎访问Cterm主页</a></p>
</table>
</body>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -