- 论坛徽章:
- 0
|
我写的基本的epoll框架,使用apache ab测试,
ab -c 1000 -n 10000 http://localhost:8080/
之后打开浏览器 页面不动 感觉阻塞了
然后继续ab测试 页面就刷出来了
大家帮忙看看。
- #include<iostream>
- #include<string>
- #include<map>
- #include<sys/types.h>
- #include<sys/socket.h>
- #include<arpa/inet.h>
- #include<unistd.h>
- #include<fcntl.h>
- #include<signal.h>
- #include<sys/epoll.h>
- #include<string.h>
- #include<error.h>
- #include<errno.h>
- #include<stdlib.h>
- #include<sys/resource.h>
- #include<pthread.h>
- #include<time.h>
- using namespace std;
- #define LISTENQ 64
- #define MAX_EVENTS 256
- #define BUFSIZE 8192
- struct client_t{
- int fd;
- string ip;
- string read_buf;
- string write_buf;
- time_t last_alive_time;
- int is_timeout;
- client_t(){
- is_timeout=0;
- }
- };
- map<int, struct client_t *> fds;
- pthread_mutex_t fds_mutex = PTHREAD_MUTEX_INITIALIZER;
- //initialize server socket
- //正常返回fd,否则返回-1
- static int
- init_servsock()
- {
- int fd;
- struct sockaddr_in serveraddr;
- //socket
- if((fd=socket(AF_INET,SOCK_STREAM,0))<0){
- perror("socket ");
- return -1;
- }
- //可重用
- socklen_t reuse=1;
- if(setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))<0){ //否则程序挂掉马上重启,会报端口不可用
- perror("setsockopt()");
- }
- serveraddr.sin_family=AF_INET;
- serveraddr.sin_port=htons(8080);
- serveraddr.sin_addr.s_addr=htonl(INADDR_ANY);
- bzero(&(serveraddr.sin_zero),8);
- //bind
- if(bind(fd,(struct sockaddr *)&serveraddr,sizeof(sockaddr))<0){
- perror("bind ");
- return -1;
- }
- //listen
- if(listen(fd,LISTENQ)){
- perror("listen ");
- return -1;
- }
- return fd;
- }
- static int
- set_fl(int fd,int flags)
- {
- int val;
- if((val = fcntl(fd,F_GETFL,0)) < 0){
- printf("fcntl F_GETFL error\n");
- return -1;
- }
- val |=flags;
- if(fcntl(fd,F_SETFL,val) < 0){
- printf("fcntl F_SETFL error\n");
- return -1;
- }
- return 0;
- }
- //超时检测
- static void *
- check_time_out(void * arg){
- int epollfd=*((int *)&arg);
- while(1){
- map<int,client_t *>::iterator it = fds.begin();
- time_t tm;
- time_t run_tm;
- time(&tm);
- for(; it!=fds.end(); ++it){
- if(it->second != NULL){
- run_tm = tm - it->second->last_alive_time;
- if(run_tm >= 10){
- pthread_mutex_lock(&fds_mutex);
- close(it->second->fd);
- delete it->second;
- it->second = NULL;
- epoll_ctl(epollfd, EPOLL_CTL_DEL, it->second->fd, NULL);
- pthread_mutex_unlock(&fds_mutex);
- }
- }
- }
- sleep(1);
- }
- }
- int
- main()
- {
- struct epoll_event ev, events[MAX_EVENTS];
- int listen_sock;
- int epollfd;
- int nfds;
- int err;
- //更改系统打开文件限制
- struct rlimit limit;
- limit.rlim_cur=getdtablesize();
- limit.rlim_max=limit.rlim_cur;
- if(setrlimit(RLIMIT_NOFILE,&limit)<0){
- perror("setrlimit");
- exit(1);
- }
-
- epollfd = epoll_create(512);
- if(epollfd == -1){
- perror("epoll_create");
- exit(1);
- }
- //创建超时检测线程
- pthread_t pid;
- err = pthread_create(&pid, NULL, check_time_out, (void *)epollfd);
- if(err !=0 ){
- printf("创建超时检测线程失败!\n");
- exit(1);
- }
- if((listen_sock = init_servsock())<0){
- exit(1);
- }
- //设置为非阻塞
- if(set_fl(listen_sock,O_NONBLOCK) < 0){
- exit(1);
- }
- //忽略信号
- signal(SIGPIPE,SIG_IGN);
- ev.events = EPOLLIN | EPOLLET;
- ev.data.fd = listen_sock;
- if(epoll_ctl(epollfd,EPOLL_CTL_ADD,listen_sock,&ev) == -1){
- perror("epoll_ctl:listen_sock");
- exit(1);
- }
- while(1){
- nfds = epoll_wait(epollfd,events,MAX_EVENTS,-1);
- if(nfds == -1){
- perror("epoll_wait");
- exit(1);
- }
- int n;
- for(n = 0; n < nfds; ++n){
- if(events[n].data.fd == listen_sock){
- struct sockaddr_in addr_in;
- size_t addrlen = sizeof(struct sockaddr_in);
- int conn_sock = accept(listen_sock, (struct sockaddr *)&addr_in, &addrlen);
- if(conn_sock == -1){
- perror("accept");
- continue;
- }
- if(set_fl(conn_sock, O_NONBLOCK) < 0){
- exit(1);
- }
- ev.events = EPOLLIN | EPOLLET;
- ev.data.fd = conn_sock;
- if(epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_sock, &ev) == -1){
- perror("epoll_ctl:conn_sock");
- exit(1);
- }
- client_t *client_ptr = new client_t;
- fds[conn_sock] = client_ptr;
- fds[conn_sock]->fd = conn_sock;
- fds[conn_sock]->ip = string(inet_ntoa(addr_in.sin_addr));
- fds[conn_sock]->last_alive_time=time(NULL);
- }else if(events[n].events & EPOLLIN){
- int fd = events[n].data.fd;
- pthread_mutex_lock(&fds_mutex);
- while(1){
- char buf[BUFSIZE];
- memset(buf, 0, BUFSIZE);
- int n=read(fd, buf, BUFSIZE);
- if(n>0){
- fds[fd]->read_buf.append(buf,BUFSIZE);
- }
- if(n < BUFSIZE){
- break;
- }
- if(errno == EAGAIN){
- break;
- }
- }
- pthread_mutex_unlock(&fds_mutex);
- ev.events = EPOLLOUT | EPOLLET;
- ev.data.fd = fd;
- epoll_ctl(epollfd, EPOLL_CTL_MOD ,fd ,&ev);
- }else if(events[n].events & EPOLLOUT){
- int fd = events[n].data.fd;
- pthread_mutex_lock(&fds_mutex);
- fds[fd]->write_buf = "HTTP/1.1 200 Ok\r\n";
- fds[fd]->write_buf += "Content-Type: text/plain\r\n";
- fds[fd]->write_buf += "Content-Length: 11\r\n";
- fds[fd]->write_buf += "\r\n";
- fds[fd]->write_buf += "hello world";
- int n = write(fd, fds[fd]->write_buf.data(), fds[fd]->write_buf.length());
- if(n < 0){
- perror("write");
- }
- epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, NULL);
- close(fd);
- delete fds[fd];
- fds[fd] = NULL;
- pthread_mutex_unlock(&fds_mutex);
- /*ev.events = EPOLLIN | EPOLLET;
- ev.data.fd = fd;
- epoll_ctl(epollfd, EPOLL_CTL_MOD, fd, &ev);*/
- }
- }
- }
- close(listen_sock);
- return 0;
- }
复制代码 |
|