加入收藏 | 设为首页 | 会员中心 | 我要投稿 云计算网_泰州站长网 (http://www.0523zz.com/)- 视觉智能、AI应用、CDN、行业物联网、智能数字人!
当前位置: 首页 > 服务器 > 搭建环境 > Unix > 正文

UNIX网络编程:并发服务器(TCP)

发布时间:2016-09-26 16:11:37 所属栏目:Unix 来源:站长网
导读:副标题#e# 在迭代服务器中,服务器只能处理一个客户端的请求,如何同时服务多个客户端呢?在未讲到select/poll/epoll等高级IO之前,比较老土的办法是使用fork来实现。 网络服务器通常用fork来同时服务多个客户端,父进程专门负责监听端口,每次accept一个新

先运行服务器程序,再运行客户端,客户端输出如下:

huangcheng@ubuntu:~$ ./cli  
local ip=127.0.0.1 port=33867  
local ip=127.0.0.1 port=33868  
local ip=127.0.0.1 port=33869  
local ip=127.0.0.1 port=33870  
local ip=127.0.0.1 port=33871  
huangcheng  
huangcheng

即每个连接的ip地址是一样的,但端口号不同,服务器方面通过accept返回的信息也打印出连接信息,如下:

huangcheng@ubuntu:~$ ./serv  
recv connect ip=127.0.0.1 port=33867  
recv connect ip=127.0.0.1 port=33868  
recv connect ip=127.0.0.1 port=33869  
recv connect ip=127.0.0.1 port=33870  
recv connect ip=127.0.0.1 port=33871  
huangcheng

当客户终止时,所有打开的描述符由内核自动关闭(我们不调用close,仅调用exit),且所有的5个连接基本在同一时刻终止。这就引发了5个FIN,每个连接一个,他们反过来使服务器的5个子进程基本在同一时刻终止。这又导致差不多在同一时刻有5个SIGCHLD信号递交给父进程:

UNIX网络编程:并发服务器(TCP)

我们预期所有的5个子进程都终止了。但是运行PS,我们发现其他4个子进程仍然作为僵死进程存在着。

正确的解决办法是调用waitpid而不是wait。我们必须指定WNOHANG选项,它告知waitpid在有尚未终止的子进程在运行时不要阻塞。我们不能再循环内调用wait,因为没有办法防止wait在运行的子进程尚未终止时阻塞。

注意前面的代码:

while (1)    
  {    
      if ((conn = accept(listenfd, (struct sockaddr *)&peeraddr, &peerlen)) < 0) //3次握手完成的序列    
      {    
          if( errno == EINTR )            ///////////////////////////////////////////////////////////////////必须处理被中断的系统调用    
             continue;    
          else
             ERR_EXIT("accept error");    
      }

这段代码所做的事情就是自己重启被中断的系统调用。对于accept以及诸如read、write、select和open之类函数来说,这是合适的。不过有一个函数我们不能重启:connect。如果该函数返回EINTR,我们就不能再次调用它,否则将立即返回一个错误。当connect被一个捕获的信号中断而且不能重启时,我们必须调用select来等待连接完成。

(编辑:云计算网_泰州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

推荐文章
    热点阅读