Linux Socket Programming by Example-第十一章 多客户端并发处理

这一章是整个书本的核心与精华。

如何处理多路并发请求?

通常有以下5种方法:

1> 每个请求,fork一个子进程进行处理
2> 每个请求,创建一个子线程进行处理
3> select
4> poll
5> epoll


方法1:
   accept请求后,执行fork()创建子进程。


   pid = fork();
   if (pid == -1) {
       //错误处理
   } 
   if (pid == 0) {
       // 父进程
       continue;
   }
   // 子进程
   // 处理请求


方法2:
accept请求后,执行pthread_create创建子线程

方法3:
fd_set rx_socks; // 接收监控集
fd_set wk_socks; // 处理监控集


  // 初始化
FD_ZERO(&rx_socks);
FD_ZERO(&wk_socks);


FD_SET(s, &read_socks); //将Server端Socket放入接收监控集
maxFD = s + 1;


for (;;) {
   // 每次调用select前,重新初始化监控集
   FD_ZERO(&wk_socks);
  for ( i = 0; i < maxFD; ++i) {
    if (FD_ISSET(i, &rx_socks)) {
       FD_SET(i, &wk_socks);
    }
  }
  // 设置超时信息
  timeOut.tv_sec = 5;
  timeOut.tv_usec = 0;
  n = select(mx, &wk_socks, NULL, NULL, &timeOut);
  if (n == -1) {
    // 错误处理
  }
  if ( n == 0) {
     // 超时处理
  }

  if ( FD_ISSET(s, &wk_socks)) { // 有Request
       调用accept,并将sock放入rx_socks
      if ( c + 1 > mx) { //更新监控fd范围
          mx = c +1;
     }
  }
  // 依次检查wk_socks是否有事件需要处理
  for ( c=0; c< mx; ++c) {
    if ( c== s) {
        continue;
    }
   if ( FD_ISSET(c, &wK_socks)) {
      //处理客户端消息
      // 如果客户端结束,则将其从rx_socks清除( FD_CLR(c, &rx_set))
   }
 }
 // 重新检查rx_socks,修正监控范围
 for (c = mx -1; (c>=0) && (!FD_ISSET(c, &rx_set)); c = c -1)
        mx = c;
}  

select方法的核心是对每个监控fd进行轮训检查,如果有事件,则相应标志位设为1.

 限制: 最多支持FD_SETSIZE(通常为1024)个并发请求。

4> poll
select与poll区别可以用下面例子来简单说明:
假设有一些同学来到了某个教室上课,老师如何知道哪些学生想提问?
select: 记录进入教室的学生的最大学号,从0到最大学号,依次轮训检查是否有问题要问,有的话就
设置为1.(明显没来教室的肯定也询问了一次, 性能浪费)
poll: 用一个记事本记录所有来教室上课的学生学号,然后依次询问该学生是否有问题要问。

接口:
#include <sys/poll.h>
struct pollfd {
int fd;         /* 文件描述符 */
short events;         /* 等待的事件 */
short revents;       /* 实际发生了的事件 */
}; 
int poll ( struct pollfd * fds, unsigned int nfds, int timeout);

使用poll就简单了,我们先将server 监控socket作为第一个元素放入
pollfd 数组中,然后调用poll,如果有request(对应POLLIN)事件,则执行
accept,并将新的连接fd放入pollfd 数组中。

缺点: 维护pollfd数组远比bit位占用更多内存,用户态与内核态交互的数据拷贝负荷大。


5>epoll
顾名思义,用阻塞event机制代替轮训poll,对poll进行了改进。

接口:
epoll_create 初始化
epoll_ctl 对监控队列进行操作
epoll_wait 阻塞,等待事件通知

参考代码:
http://www.cnblogs.com/ggjucheng/archive/2012/01/17/2324974.html


关于select / poll /epoll的分析比较可以参考以下博客:
http://blog.sina.com.cn/s/blog_8fa7dd41010153zx.html


个人项目体会,一般情况下用select,高连接(>5000)下用epoll。

Linux Socket Programming by Example-第十一章 多客户端并发处理,布布扣,bubuko.com

Linux Socket Programming by Example-第十一章 多客户端并发处理

上一篇:缓存应用--Memcached分布式缓存简介


下一篇:Linux 文件权限于目录配置