码迷,mamicode.com
首页 > 其他好文 > 详细

epoll的et和lt模式

时间:2015-08-17 18:52:30      阅读:139      评论:0      收藏:0      [点我收藏+]

标签:

  1 //《linux高性能服务器编程》9.3章
  2 //略微改了些代码
  3 
  4 #include <iostream>
  5 using namespace std;
  6 
  7 #include <sys/types.h>
  8 #include <sys/socket.h>
  9 #include <netinet/in.h>
 10 #include <unistd.h>
 11 #include <errno.h>
 12 #include <string.h>
 13 #include <sys/epoll.h>
 14 #include <fcntl.h>
 15 
 16 #define MAX_EVENTS 1024
 17 #define BUFFER_SIZE 10
 18 
 19 //设置非阻塞
 20 void setnonblocking(int fd)
 21 {
 22     int oldfd = fcntl(fd, F_GETFL);
 23     int newfd = oldfd | O_NONBLOCK;
 24     fcntl(fd, F_SETFL, newfd);
 25 }
 26 
 27 //epoll注册
 28 void addfd(int epollfd, int fd, bool bET)
 29 {
 30     epoll_event event;
 31     event.data.fd = fd;
 32     event.events = EPOLLIN;
 33 
 34     //设置ET模式
 35     if(bET)
 36     {
 37         event.events |= EPOLLET;    
 38     }
 39     epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event);
 40     setnonblocking(fd);
 41 }
 42 
 43 void epollwork(epoll_event* events, int number, int epollfd, int listenfd, bool bET)
 44 {
 45     char buf[BUFFER_SIZE];
 46     for(int i=0; i<number; i++)
 47     {
 48         int sockfd = events[i].data.fd;
 49         //conn
 50         if(sockfd == listenfd)
 51         {
 52             sockaddr_in cliAddr;
 53             socklen_t cliLen = sizeof(cliAddr);
 54             int connfd = accept(listenfd, (sockaddr*)&cliAddr, &cliLen);    
 55             if(connfd < 0 )
 56             {cout<<"accept error"<<endl;continue;}
 57 
 58             addfd(epollfd, connfd, true);
 59 
 60             cout<<"conn:"<<connfd<<","<<endl;
 61         }
 62         //recv
 63         else if(events[i].events & EPOLLIN)
 64         {
 65             //et
 66             if(bET)
 67             {
 68             //ET循环处理内核缓存数据,
 69             while(true)    
 70             {
 71                 memset(buf, 0, BUFFER_SIZE);        
 72                 int ret = recv(sockfd, buf, sizeof(buf)-1, 0);
 73                 if(ret < 0)
 74                 {
 75                     if((errno == EAGAIN) || (errno == EWOULDBLOCK))    
 76                     {break;}
 77 
 78                     close(sockfd);
 79                     break;
 80                 }
 81                 else if(ret == 0)
 82                 {
 83                     close(sockfd);    
 84                 }
 85                 buf[ret] = \0;
 86                 cout<<"recv:"<<buf<<endl;
 87             }
 88 
 89             }
 90             //lt
 91             else
 92             {
 93                 //接收一次数据。如系统内核有缓存数据,epoll_wait能再次处理
 94                 memset(buf, 0, BUFFER_SIZE);    
 95                 int ret = recv(sockfd, buf, sizeof(buf)-1, 0);
 96                 if(ret < 0)
 97                 {
 98                     close(sockfd);    
 99                     continue;
100                 }
101                 buf[ret] = \0;
102                 cout<<"recv:"<<buf<<endl;
103             }
104         }
105         else
106         {
107             //todo send    
108         }
109             
110     }
111 }
112 
113 int main(int argc, char** argv)
114 {
115     //默认为LT模式,启动附加参数就启用ET模式。便于调试
116     bool bET = false;
117     if(argc > 1)
118     {
119         bET = true;    
120     }
121     const char* ip = "127.0.0.1";
122     int port = 9999;
123 
124     //1.socket
125     int listenfd = socket(PF_INET, SOCK_STREAM, 0);
126     if(listenfd < 0)
127     {
128         cout<<"socket error"<<endl;
129     }
130 
131     //2.bind
132     sockaddr_in addr;
133     addr.sin_family = AF_INET;
134     addr.sin_port = htons(port);
135     addr.sin_addr.s_addr = htonl(INADDR_ANY);
136     if(bind(listenfd, (sockaddr*)&addr, sizeof(addr)) == -1)
137     {
138         cout<<"bind error"<<endl;    
139     }
140 
141     //3.listen
142     if(listen(listenfd, 5) == -1)
143     {cout<<"listen error"<<endl;}
144 
145     //4.epoll
146     epoll_event events[MAX_EVENTS];
147     //创建
148     int epollfd = epoll_create(50);
149     if(epollfd == -1)
150     {cout<<"epoll_create error"<<endl;}
151     //注册
152     addfd(epollfd, listenfd, bET);
153     
154     //5.
155     while(true)
156     {
157         //获取
158         int ret = epoll_wait(epollfd, events, MAX_EVENTS, -1);    
159         if(ret < 0)
160         {cout<<"epoll_wait error"<<endl;}
161 
162         //处理
163         epollwork(events, ret, epollfd, listenfd, bET);
164     }
165 
166     close(listenfd);
167     return 0;
168 }
169 
170 //编译g++ -o epoll2 epoll2.cpp
171 //LT模式
172 //1.启动该服务,输入./epoll2
173 //2.ctrl+alt+f2,命令输入telnet 127.0.0.1 9999
174 //3.发送字符:aaaaabbbbbccccc  接收为:aaaaabbbb
175 //  发送字符: wjt              接收为:bcccccwjt
176 
177 //ET模式
178 //1.启动该服务,输入./epoll2 et
179 //2.ctrl+alt+f2,命令输入telnet 127.0.0.1 9999
180 //3.发送字符:aaaaabbbbbccccc  接收为:aaaaabbbb
181 //                             接收为:bccccc

 

epoll的et和lt模式

标签:

原文地址:http://www.cnblogs.com/optao/p/4737206.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!