epoll的et和lt模式(5)

//现在用linux做服务器,高并发的epoll占了很重要部分吧。
//设计模式+epoll+fcntl全都可以开发了,这些如果没在项目中实践,要理解也是挺难的。

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

 

转载于:https://www.cnblogs.com/optao/p/4737206.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值