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

📄 linux网络编程--9. 服务器模型.html

📁 Linux网络编程
💻 HTML
📖 第 1 页 / 共 2 页
字号:
</tr><td align=center><table border="0" width="80%"  cellspacing="0" cellpadding="0" align=center><tr><td valign=top><font color=#cccccc>
<br>&nbsp;&nbsp;&nbsp;&nbsp;学习过《软件工程》吧.软件工程可是每一个程序员"必修"的课程啊.如果你没有学习过,&nbsp;建议你去看一看.&nbsp;在这一章里面,我们一起来从软件工程的角度学习网络编程的思想.在我们写程序之前,&nbsp;我们都应该从软件工程的角度规划好我们的软件,这样我们开发软件的效率才会高.&nbsp;在网络程序里面,一般的来说都是许多客户机对应一个服务器.为了处理客户机的请求,&nbsp;对服务端的程序就提出了特殊的要求.我们学习一下目前最常用的服务器模型.&nbsp;
<br>
<br>循环服务器:循环服务器在同一个时刻只可以响应一个客户端的请求&nbsp;
<br>
<br>并发服务器:并发服务器在同一个时刻可以响应多个客户端的请求&nbsp;
<br>
<br>
<br>9.1&nbsp;循环服务器:UDP服务器&nbsp;
<br>UDP循环服务器的实现非常简单:UDP服务器每次从套接字上读取一个客户端的请求,处理,&nbsp;然后将结果返回给客户机.&nbsp;
<br>
<br>可以用下面的算法来实现.&nbsp;
<br>
<br>&nbsp;&nbsp;&nbsp;socket(...);
<br>&nbsp;&nbsp;&nbsp;bind(...);
<br>&nbsp;&nbsp;&nbsp;while(1)
<br>&nbsp;&nbsp;&nbsp;&nbsp;{
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;recvfrom(...);
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;process(...);
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sendto(...);
<br>&nbsp;&nbsp;&nbsp;}
<br>
<br>因为UDP是非面向连接的,没有一个客户端可以老是占住服务端.&nbsp;只要处理过程不是死循环,&nbsp;服务器对于每一个客户机的请求总是能够满足.&nbsp;
<br>9.2&nbsp;循环服务器:TCP服务器&nbsp;
<br>TCP循环服务器的实现也不难:TCP服务器接受一个客户端的连接,然后处理,完成了这个客户的所有请求后,断开连接.&nbsp;
<br>
<br>算法如下:&nbsp;
<br>
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket(...);
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bind(...);
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listen(...);
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(1)
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;accept(...);
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(1)
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;read(...);
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;process(...);
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;write(...);
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;close(...);
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
<br>
<br>TCP循环服务器一次只能处理一个客户端的请求.只有在这个客户的所有请求都满足后,&nbsp;服务器才可以继续后面的请求.这样如果有一个客户端占住服务器不放时,其它的客户机都不能工作了.因此,TCP服务器一般很少用循环服务器模型的.&nbsp;
<br>
<br>9.3&nbsp;并发服务器:TCP服务器&nbsp;
<br>为了弥补循环TCP服务器的缺陷,人们又想出了并发服务器的模型.&nbsp;并发服务器的思想是每一个客户机的请求并不由服务器直接处理,而是服务器创建一个&nbsp;子进程来处理.&nbsp;
<br>
<br>算法如下:&nbsp;
<br>
<br>&nbsp;&nbsp;socket(...);
<br>&nbsp;&nbsp;bind(...);
<br>&nbsp;&nbsp;listen(...);
<br>&nbsp;&nbsp;while(1)
<br>&nbsp;&nbsp;{
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;accept(...);
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(fork(..)==0)
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(1)
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;read(...);
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;process(...);
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;write(...);
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;close(...);
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(...);
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;close(...);
<br>&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<br>
<br>TCP并发服务器可以解决TCP循环服务器客户机独占服务器的情况.&nbsp;不过也同时带来了一个不小的问题.为了响应客户机的请求,服务器要创建子进程来处理.&nbsp;而创建子进程是一种非常消耗资源的操作.&nbsp;
<br>
<br>9.4&nbsp;并发服务器:多路复用I/O&nbsp;
<br>为了解决创建子进程带来的系统资源消耗,人们又想出了多路复用I/O模型.&nbsp;
<br>
<br>首先介绍一个函数select&nbsp;
<br>
<br>&nbsp;int&nbsp;select(int&nbsp;nfds,fd_set&nbsp;*readfds,fd_set&nbsp;*writefds,
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd_set&nbsp;*except&nbsp;fds,struct&nbsp;timeval&nbsp;*timeout)
<br>&nbsp;void&nbsp;FD_SET(int&nbsp;fd,fd_set&nbsp;*fdset)
<br>&nbsp;void&nbsp;FD_CLR(int&nbsp;fd,fd_set&nbsp;*fdset)
<br>&nbsp;void&nbsp;FD_ZERO(fd_set&nbsp;*fdset)
<br>&nbsp;int&nbsp;FD_ISSET(int&nbsp;fd,fd_set&nbsp;*fdset)
<br>
<br>一般的来说当我们在向文件读写时,进程有可能在读写出阻塞,直到一定的条件满足.&nbsp;比如我们从一个套接字读数据时,可能缓冲区里面没有数据可读(通信的对方还没有&nbsp;发送数据过来),这个时候我们的读调用就会等待(阻塞)直到有数据可读.如果我们不&nbsp;希望阻塞,我们的一个选择是用select系统调用.&nbsp;只要我们设置好select的各个参数,那么当文件可以读写的时候select回"通知"我们&nbsp;说可以读写了.&nbsp;readfds所有要读的文件文件描述符的集合&nbsp;
<br>writefds所有要的写文件文件描述符的集合&nbsp;
<br>
<br>exceptfds其他的服要向我们通知的文件描述符&nbsp;
<br>
<br>timeout超时设置.&nbsp;
<br>
<br>nfds所有我们监控的文件描述符中最大的那一个加1&nbsp;
<br>
<br>在我们调用select时进程会一直阻塞直到以下的一种情况发生.&nbsp;1)有文件可以读.2)有文件可以写.3)超时所设置的时间到.&nbsp;
<br>
<br>为了设置文件描述符我们要使用几个宏.&nbsp;FD_SET将fd加入到fdset&nbsp;
<br>
<br>FD_CLR将fd从fdset里面清除&nbsp;
<br>
<br>FD_ZERO从fdset中清除所有的文件描述符&nbsp;
<br>
<br>FD_ISSET判断fd是否在fdset集合中&nbsp;
<br>
<br>使用select的一个例子&nbsp;
<br>
<br>int&nbsp;use_select(int&nbsp;*readfd,int&nbsp;n)
<br>{
<br>&nbsp;&nbsp;&nbsp;fd_set&nbsp;my_readfd;
<br>&nbsp;&nbsp;&nbsp;int&nbsp;maxfd;
<br>&nbsp;&nbsp;&nbsp;int&nbsp;i;
<br>&nbsp;&nbsp;&nbsp;
<br>&nbsp;&nbsp;&nbsp;maxfd=readfd[0];
<br>&nbsp;&nbsp;&nbsp;for(i=1;i<n;i++)
<br>&nbsp;&nbsp;&nbsp;&nbsp;if(readfd[i]>maxfd)&nbsp;maxfd=readfd[i];
<br>&nbsp;&nbsp;&nbsp;while(1)
<br>&nbsp;&nbsp;&nbsp;{
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;&nbsp;&nbsp;将所有的文件描述符加入&nbsp;&nbsp;&nbsp;*/
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FD_ZERO(&my_readfd);
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(i=0;i<n;i++)
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FD_SET(readfd[i],*my_readfd);
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;进程阻塞&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;select(maxfd+1,&&nbsp;my_readfd,NULL,NULL,NULL);&nbsp;
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;有东西可以读了&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(i=0;i<n;i++)
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(FD_ISSET(readfd[i],&my_readfd))
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;原来是我可以读了&nbsp;&nbsp;*/&nbsp;
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;we_read(readfd[i]);
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
<br>&nbsp;&nbsp;&nbsp;}
<br>}
<br>
<br>使用select后我们的服务器程序就变成了.&nbsp;
<br>
<br>
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;初始话(socket,bind,listen);
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<br>&nbsp;&nbsp;&nbsp;&nbsp;while(1)
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;设置监听读写文件描述符(FD_*);&nbsp;&nbsp;&nbsp;
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;调用select;
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果是倾听套接字就绪,说明一个新的连接请求建立
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;建立连接(accept);
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;加入到监听文件描述符中去;
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;否则说明是一个已经连接过的描述符
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;进行操作(read或者write);
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<br>
<br>多路复用I/O可以解决资源限制的问题.着模型实际上是将UDP循环模型用在了TCP上面.&nbsp;这也就带来了一些问题.如由于服务器依次处理客户的请求,所以可能会导致有的客户&nbsp;会等待很久.&nbsp;
<br>
<br>9.5&nbsp;并发服务器:UDP服务器&nbsp;
<br>人们把并发的概念用于UDP就得到了并发UDP服务器模型.&nbsp;并发UDP服务器模型其实是简单的.和并发的TCP服务器模型一样是创建一个子进程来处理的&nbsp;算法和并发的TCP模型一样.&nbsp;
<br>
<br>除非服务器在处理客户端的请求所用的时间比较长以外,人们实际上很少用这种模型.&nbsp;
<br>
<br>
<br>9.6&nbsp;一个并发TCP服务器实例&nbsp;
<br>
<br>#include&nbsp;<sys/socket.h>
<br>#include&nbsp;<sys/types.h>
<br>#include&nbsp;<netinet/in.h>
<br>#include&nbsp;<string.h>
<br>#include&nbsp;<errno.h>
<br>#define&nbsp;MY_PORT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8888
<br>
<br>int&nbsp;main(int&nbsp;argc&nbsp;,char&nbsp;**argv)
<br>{
<br>&nbsp;int&nbsp;listen_fd,accept_fd;
<br>&nbsp;struct&nbsp;sockaddr_in&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;client_addr;
<br>&nbsp;int&nbsp;n;
<br>&nbsp;
<br>&nbsp;if((listen_fd=socket(AF_INET,SOCK_STREAM,0))<0)
<br>&nbsp;&nbsp;{
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("Socket&nbsp;Error:%s\n\a",strerror(errno));
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1);
<br>&nbsp;&nbsp;}
<br>&nbsp;
<br>&nbsp;bzero(&client_addr,sizeof(struct&nbsp;sockaddr_in));
<br>&nbsp;client_addr.sin_family=AF_INET;
<br>&nbsp;client_addr.sin_port=htons(MY_PORT);
<br>&nbsp;client_addr.sin_addr.s_addr=htonl(INADDR_ANY);
<br>&nbsp;n=1;
<br>&nbsp;/*&nbsp;如果服务器终止后,服务器可以第二次快速启动而不用等待一段时间&nbsp;&nbsp;*/
<br>&nbsp;setsockopt(listen_fd,SOL_SOCKET,SO_REUSEADDR,&n,sizeof(int));
<br>&nbsp;if(bind(listen_fd,(struct&nbsp;sockaddr&nbsp;*)&client_addr,sizeof(client_addr))<0)
<br>&nbsp;&nbsp;{
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("Bind&nbsp;Error:%s\n\a",strerror(errno));
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1);
<br>&nbsp;&nbsp;}
<br>&nbsp;&nbsp;listen(listen_fd,5);
<br>&nbsp;&nbsp;while(1)
<br>&nbsp;&nbsp;{
<br>&nbsp;&nbsp;&nbsp;accept_fd=accept(listen_fd,NULL,NULL);
<br>&nbsp;&nbsp;&nbsp;if((accept_fd<0)&&(errno==EINTR))
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue;
<br>&nbsp;&nbsp;&nbsp;else&nbsp;if(accept_fd<0)
<br>&nbsp;&nbsp;&nbsp;&nbsp;{
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("Accept&nbsp;Error:%s\n\a",strerror(errno));
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue;
<br>&nbsp;&nbsp;&nbsp;&nbsp;}
<br>&nbsp;&nbsp;if((n=fork())==0)
<br>&nbsp;&nbsp;&nbsp;{
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;子进程处理客户端的连接&nbsp;*/
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;buffer[1024];
<br>
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;close(listen_fd);
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n=read(accept_fd,buffer,1024);
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;write(accept_fd,buffer,n);
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;close(accept_fd);
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(0);
<br>&nbsp;&nbsp;&nbsp;}
<br>&nbsp;&nbsp;&nbsp;else&nbsp;if(n<0)
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("Fork&nbsp;Error:%s\n\a",strerror(errno));
<br>&nbsp;&nbsp;&nbsp;close(accept_fd);
<br>&nbsp;&nbsp;}
<br>}&nbsp;
<br>
<br>你可以用我们前面写客户端程序来调试着程序,或者是用来telnet调试&nbsp;
<br></font></td></tr><tr><td><hr></td></tr><form method=post action=/cgi-bin/find.cgi><tr><td><b>相关文章</b>  关键词 <input type=text name=key value='Linux网络编程'> <input type=submit value=搜索></td></tr></form><tr><td><a href=/a4/b7/20010508/112324.html>Linux网络编程--8. 套接字选项</a> <small>(2001-05-08 11:23:24)</small></font><br><a href=/a4/b7/20010508/112240.html>Linux网络编程--7. TCP/IP协议</a> <small>(2001-05-08 11:22:40)</small></font><br><a href=/a4/b7/20010508/112209.html>Linux网络编程--6. 高级套接字函数</a> <small>(2001-05-08 11:22:09)</small></font><br><a href=/a4/b7/20010508/112131.html>Linux网络编程--5. 用户数据报发送</a> <small>(2001-05-08 11:21:31)</small></font><br><a href=/a4/b7/20010508/112052.html>Linux网络编程--4. 完整的读写函数</a> <small>(2001-05-08 11:20:52)</small></font><br><a href=/a4/b7/20010508/112014.html>Linux网络编程--3. 服务器和客户机的信息函数</a> <small>(2001-05-08 11:20:14)</small></font><br><a href=/a4/b7/20010508/111934.html>Linux网络编程--2. 初等网络函数介绍(TCP)</a> <small>(2001-05-08 11:19:34)</small></font><br><a href=/a4/b7/20010508/111655.html>Linux网络编程--1. Linux网络知识介绍</a> <small>(2001-05-08 11:16:55)</small></font><br></td></tr><tr><td>&nbsp;</td></tr></table></td></tr><tr>  <td width="100%" height="2" colspan="5" bgcolor="#D09F0D"><img src="/images/c.gif" width=1 height=1></td> </tr><tr>    <td width="100%" height="40" colspan="5" valign=top><p align="center"><font color=#ffffff>&copy; &nbsp;&nbsp;樊强制作 欢迎分享 2001 </font></p></td>  </tr></table></center></div><img src="/cgi-bin/pagehit.cgi?filename=a4/b7/20010508/112359.html" width=1 height=1></body></html>

⌨️ 快捷键说明

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