免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2942 | 回复: 1
打印 上一主题 下一主题

epoll 框架问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-12-26 20:40 |只看该作者 |倒序浏览
我写的基本的epoll框架,使用apache ab测试,
ab -c 1000 -n 10000 http://localhost:8080/   
之后打开浏览器  页面不动  感觉阻塞了
然后继续ab测试 页面就刷出来了
大家帮忙看看。

  1. #include<iostream>
  2. #include<string>
  3. #include<map>
  4. #include<sys/types.h>
  5. #include<sys/socket.h>
  6. #include<arpa/inet.h>
  7. #include<unistd.h>
  8. #include<fcntl.h>
  9. #include<signal.h>
  10. #include<sys/epoll.h>
  11. #include<string.h>
  12. #include<error.h>
  13. #include<errno.h>
  14. #include<stdlib.h>
  15. #include<sys/resource.h>
  16. #include<pthread.h>
  17. #include<time.h>

  18. using namespace std;

  19. #define LISTENQ 64
  20. #define MAX_EVENTS 256
  21. #define BUFSIZE 8192

  22. struct client_t{
  23.         int fd;
  24.         string ip;
  25.         string read_buf;
  26.         string write_buf;
  27.         time_t last_alive_time;
  28.         int is_timeout;
  29.         client_t(){
  30.                 is_timeout=0;
  31.         }
  32. };

  33. map<int, struct client_t *> fds;
  34. pthread_mutex_t fds_mutex = PTHREAD_MUTEX_INITIALIZER;

  35. //initialize server socket
  36. //正常返回fd,否则返回-1
  37. static int
  38. init_servsock()
  39. {
  40.         int fd;
  41.         struct sockaddr_in serveraddr;
  42.         //socket
  43.         if((fd=socket(AF_INET,SOCK_STREAM,0))<0){
  44.                 perror("socket ");
  45.                 return -1;
  46.         }

  47.         //可重用
  48.         socklen_t reuse=1;
  49.         if(setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))<0){ //否则程序挂掉马上重启,会报端口不可用
  50.                 perror("setsockopt()");
  51.         }

  52.         serveraddr.sin_family=AF_INET;
  53.         serveraddr.sin_port=htons(8080);
  54.         serveraddr.sin_addr.s_addr=htonl(INADDR_ANY);
  55.         bzero(&(serveraddr.sin_zero),8);
  56.         //bind
  57.         if(bind(fd,(struct sockaddr *)&serveraddr,sizeof(sockaddr))<0){
  58.                 perror("bind ");
  59.                 return -1;
  60.         }
  61.         //listen
  62.         if(listen(fd,LISTENQ)){
  63.                 perror("listen ");
  64.                 return -1;
  65.         }

  66.         return fd;
  67. }

  68. static int
  69. set_fl(int fd,int flags)
  70. {
  71.         int val;

  72.         if((val = fcntl(fd,F_GETFL,0)) < 0){
  73.                 printf("fcntl F_GETFL error\n");
  74.                 return -1;
  75.         }

  76.         val |=flags;

  77.         if(fcntl(fd,F_SETFL,val) < 0){
  78.                 printf("fcntl F_SETFL error\n");
  79.                 return -1;
  80.         }

  81.         return 0;
  82. }

  83. //超时检测
  84. static void *
  85. check_time_out(void * arg){
  86.         int epollfd=*((int *)&arg);
  87.         while(1){
  88.                 map<int,client_t *>::iterator it = fds.begin();
  89.                 time_t tm;
  90.                 time_t run_tm;
  91.                 time(&tm);
  92.                 for(; it!=fds.end(); ++it){
  93.                         if(it->second != NULL){
  94.                                 run_tm = tm - it->second->last_alive_time;
  95.                                 if(run_tm >= 10){
  96.                                         pthread_mutex_lock(&fds_mutex);
  97.                                         close(it->second->fd);
  98.                                         delete it->second;
  99.                                         it->second = NULL;
  100.                                         epoll_ctl(epollfd, EPOLL_CTL_DEL, it->second->fd, NULL);
  101.                                         pthread_mutex_unlock(&fds_mutex);
  102.                                 }
  103.                         }
  104.                 }
  105.                 sleep(1);
  106.         }
  107. }

  108. int
  109. main()
  110. {
  111.         struct epoll_event ev, events[MAX_EVENTS];
  112.         int listen_sock;
  113.         int epollfd;
  114.         int nfds;
  115.         int err;

  116.         //更改系统打开文件限制
  117.         struct rlimit limit;
  118.         limit.rlim_cur=getdtablesize();
  119.         limit.rlim_max=limit.rlim_cur;
  120.         if(setrlimit(RLIMIT_NOFILE,&limit)<0){
  121.                 perror("setrlimit");
  122.                 exit(1);
  123.         }
  124.        

  125.         epollfd = epoll_create(512);
  126.         if(epollfd == -1){
  127.                 perror("epoll_create");
  128.                 exit(1);
  129.         }

  130.         //创建超时检测线程
  131.         pthread_t pid;
  132.         err = pthread_create(&pid, NULL, check_time_out, (void *)epollfd);
  133.         if(err !=0 ){
  134.                 printf("创建超时检测线程失败!\n");
  135.                 exit(1);
  136.         }

  137.         if((listen_sock = init_servsock())<0){
  138.                 exit(1);
  139.         }

  140.         //设置为非阻塞
  141.         if(set_fl(listen_sock,O_NONBLOCK) < 0){
  142.                 exit(1);
  143.         }

  144.         //忽略信号
  145.         signal(SIGPIPE,SIG_IGN);

  146.         ev.events = EPOLLIN | EPOLLET;
  147.         ev.data.fd = listen_sock;
  148.         if(epoll_ctl(epollfd,EPOLL_CTL_ADD,listen_sock,&ev) == -1){
  149.                 perror("epoll_ctl:listen_sock");
  150.                 exit(1);
  151.         }

  152.         while(1){
  153.                 nfds = epoll_wait(epollfd,events,MAX_EVENTS,-1);
  154.                 if(nfds == -1){
  155.                         perror("epoll_wait");
  156.                         exit(1);
  157.                 }

  158.                 int n;
  159.                 for(n = 0; n < nfds; ++n){
  160.                         if(events[n].data.fd == listen_sock){
  161.                                 struct sockaddr_in addr_in;
  162.                                 size_t addrlen = sizeof(struct sockaddr_in);
  163.                                 int conn_sock = accept(listen_sock, (struct sockaddr *)&addr_in, &addrlen);
  164.                                 if(conn_sock == -1){
  165.                                         perror("accept");
  166.                                         continue;
  167.                                 }

  168.                                 if(set_fl(conn_sock, O_NONBLOCK) < 0){
  169.                                         exit(1);
  170.                                 }
  171.                                 ev.events = EPOLLIN | EPOLLET;
  172.                                 ev.data.fd = conn_sock;
  173.                                 if(epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_sock, &ev) == -1){
  174.                                         perror("epoll_ctl:conn_sock");
  175.                                         exit(1);
  176.                                 }

  177.                                 client_t *client_ptr = new client_t;
  178.                                 fds[conn_sock] = client_ptr;
  179.                                 fds[conn_sock]->fd = conn_sock;
  180.                                 fds[conn_sock]->ip = string(inet_ntoa(addr_in.sin_addr));
  181.                                 fds[conn_sock]->last_alive_time=time(NULL);
  182.                         }else if(events[n].events & EPOLLIN){
  183.                                 int fd = events[n].data.fd;
  184.                                 pthread_mutex_lock(&fds_mutex);
  185.                                 while(1){
  186.                                         char buf[BUFSIZE];
  187.                                         memset(buf, 0, BUFSIZE);
  188.                                         int n=read(fd, buf, BUFSIZE);
  189.                                         if(n>0){
  190.                                                 fds[fd]->read_buf.append(buf,BUFSIZE);
  191.                                         }
  192.                                         if(n < BUFSIZE){
  193.                                                 break;
  194.                                         }
  195.                                         if(errno == EAGAIN){
  196.                                                 break;
  197.                                         }
  198.                                 }
  199.                                 pthread_mutex_unlock(&fds_mutex);
  200.                                 ev.events = EPOLLOUT | EPOLLET;
  201.                                 ev.data.fd = fd;
  202.                                 epoll_ctl(epollfd, EPOLL_CTL_MOD ,fd ,&ev);
  203.                         }else if(events[n].events & EPOLLOUT){
  204.                                 int fd = events[n].data.fd;
  205.                                 pthread_mutex_lock(&fds_mutex);
  206.                                 fds[fd]->write_buf = "HTTP/1.1 200 Ok\r\n";
  207.                                 fds[fd]->write_buf += "Content-Type: text/plain\r\n";
  208.                                 fds[fd]->write_buf += "Content-Length: 11\r\n";
  209.                                 fds[fd]->write_buf += "\r\n";
  210.                                 fds[fd]->write_buf += "hello world";
  211.                                 int n = write(fd, fds[fd]->write_buf.data(), fds[fd]->write_buf.length());
  212.                                 if(n < 0){
  213.                                         perror("write");
  214.                                 }

  215.                                 epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, NULL);
  216.                                 close(fd);
  217.                                 delete fds[fd];
  218.                                 fds[fd] = NULL;
  219.                                 pthread_mutex_unlock(&fds_mutex);

  220.                                 /*ev.events = EPOLLIN | EPOLLET;
  221.                                 ev.data.fd = fd;
  222.                                 epoll_ctl(epollfd, EPOLL_CTL_MOD, fd, &ev);*/
  223.                         }
  224.                 }
  225.         }


  226.         close(listen_sock);

  227.         return 0;
  228. }
复制代码

论坛徽章:
0
2 [报告]
发表于 2009-12-26 21:12 |只看该作者
strace之
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP