epoll案例
1 #include <stdio.h> 2 #include <string.h> 3 #include <errno.h> 4 5 #include <iostream> 6 7 #include <sys/socket.h> 8 #include <netdb.h> 9 #include <arpa/inet.h> 10 11 #include <fcntl.h> 12 #include <unistd.h> 13 14 #include <sys/epoll.h> 15 16 #define MAX_EVENTS 1024 17 18 using namespace std; 19 20 static int setSocketNonBlock(const int socketFd) 21 { 22 int ret(0); 23 24 int flags = fcntl(socketFd, F_GETFL, 0); 25 if (-1 == flags) 26 { 27 cerr << "fcntl error" << endl; 28 return -1; 29 } 30 31 flags |= O_NONBLOCK; 32 ret = fcntl(socketFd, F_SETFL, flags); 33 if (-1 == ret) 34 { 35 cerr << "fcntl error" << endl; 36 return -1; 37 } 38 39 return 0; 40 } 41 42 static int setSocketLingerDisable(const int socketFd) 43 { 44 int ret(0); 45 46 struct linger lingerVal; 47 lingerVal.l_onoff = 1; 48 lingerVal.l_linger = 0; 49 ret = setsockopt(socketFd, SOL_SOCKET, SO_LINGER, &lingerVal, sizeof(struct linger)); 50 if (0 != ret) 51 { 52 cerr << "setsockopt" << endl; 53 return -1; 54 } 55 56 return 0; 57 } 58 59 static int create_and_bind() 60 { 61 int ret(0); 62 63 struct addrinfo hints; 64 struct addrinfo * retAddr, * retNext; 65 66 memset(&hints, 0, sizeof(struct addrinfo)); 67 hints.ai_family = AF_UNSPEC; 68 hints.ai_socktype = SOCK_STREAM; 69 hints.ai_protocol = IPPROTO_TCP; 70 hints.ai_flags = AI_PASSIVE; 71 ret = getaddrinfo(NULL, "8090", &hints, &retAddr); 72 if (0 != ret) 73 { 74 cerr << "getaddrinfo" << endl; 75 return -1; 76 } 77 78 int listenSocket(-1); 79 80 for (retNext = retAddr; retNext != NULL; retNext = retNext->ai_next) 81 { 82 // char ipBuf[1024]; 83 // switch(retNext->ai_family) 84 // { 85 // case AF_INET: 86 // inet_ntop(AF_INET, &((struct sockaddr_in *)(retNext->ai_addr))->sin_addr, ipBuf, sizeof(char[1024])); 87 // break; 88 // case AF_INET6: 89 // inet_ntop(AF_INET6, &((struct sockaddr_in6 *)(retNext->ai_addr))->sin6_addr, ipBuf, sizeof(char[1024])); 90 // break; 91 // } 92 // cout << "ipBuf: " << ipBuf << endl; 93 94 listenSocket = socket(retNext->ai_family, retNext->ai_socktype, retNext->ai_protocol); 95 if (-1 == listenSocket) 96 { 97 cerr << "socket error" << endl; 98 continue; 99 } 100 101 ret = bind(listenSocket, retNext->ai_addr, retNext->ai_addrlen); 102 if (0 != ret) 103 { 104 cerr << " bind error" << endl; 105 close(listenSocket); 106 continue; 107 } 108 109 break; // 已成功生成并绑定监听socket, 退出for遍历 110 } 111 112 freeaddrinfo(retAddr); 113 114 if (NULL == retNext) 115 { 116 cerr << "create_and_bind error" << endl; 117 return 1; 118 } 119 120 return listenSocket; 121 } 122 123 int main(int argc, char **argv) 124 { 125 int ret(0); 126 127 int listenSocket(-1); 128 listenSocket = create_and_bind(); 129 if (-1 == listenSocket) 130 { 131 return -1; 132 } 133 134 ret = setSocketNonBlock(listenSocket); 135 if (0 != ret) 136 { 137 return -1; 138 } 139 140 ret = setSocketLingerDisable(listenSocket); 141 if (0 != ret) 142 { 143 return -1; 144 } 145 146 ret = listen(listenSocket, 10); 147 if (0 != ret) 148 { 149 cerr << "listen error" << endl; 150 return -1; 151 } 152 153 int epollFd(-1); 154 epollFd = epoll_create1(0); 155 if (-1 == epollFd) 156 { 157 cerr << "epoll_create1 error" << endl; 158 return -1; 159 } 160 161 // 监听socket注册到epollFd中管理 162 struct epoll_event event; 163 event.data.fd = listenSocket; 164 event.events = EPOLLET | EPOLLIN; 165 ret = epoll_ctl(epollFd, EPOLL_CTL_ADD, listenSocket, &event); 166 if (0 != ret) 167 { 168 cerr << "epoll_ctl error" << endl; 169 return -1; 170 } 171 172 struct epoll_event retEvents[MAX_EVENTS]; 173 174 bool done(false); 175 int retEventsCnt(0); 176 while (!done) 177 { 178 retEventsCnt = epoll_wait(epollFd, retEvents, MAX_EVENTS, 1000); 179 cout << "retEventCnt: " << retEventsCnt << endl; 180 for (int i = 0; i < retEventsCnt; ++i) 181 { 182 if ((retEvents[i].events & EPOLLERR) || (retEvents[i].events & EPOLLHUP) || 183 !(retEvents[i].events & EPOLLIN)) 184 { 185 cerr << "socketFd: " << retEvents[i].data.fd << " error" << endl; 186 close(retEvents[i].data.fd); 187 continue; 188 } 189 else if (listenSocket == retEvents[i].data.fd) 190 { 191 while (true) 192 { 193 struct sockaddr remoteSockAddr; 194 socklen_t len = sizeof(struct sockaddr); 195 196 int connectSocket(-1); 197 connectSocket = accept(listenSocket, &remoteSockAddr, &len); 198 if (-1 == connectSocket) 199 { 200 if (EAGAIN == errno) 201 { 202 break; 203 } 204 else 205 { 206 cerr << "accept error" << endl; 207 continue; 208 } 209 } 210 211 char hostStr[100]; 212 char serviceStr[100]; 213 ret = getnameinfo(&remoteSockAddr, sizeof(struct sockaddr), hostStr, sizeof(char[100]), 214 serviceStr, sizeof(char[100]), 0); 215 if (0 == ret) 216 { 217 printf("client info: [connectSocket: %d, host: %s, port: %s]\n", connectSocket, hostStr, serviceStr); 218 } 219 220 ret = setSocketNonBlock(connectSocket); 221 if (0 != ret) 222 { 223 return -1; 224 } 225 226 ret = setSocketLingerDisable(connectSocket); 227 if (0 != ret) 228 { 229 return -1; 230 } 231 232 event.data.fd = connectSocket; 233 event.events = EPOLLET | EPOLLIN; 234 235 ret = epoll_ctl(epollFd, EPOLL_CTL_ADD, connectSocket, &event); 236 if (0 != ret) 237 { 238 cerr << "epoll_ctl error" << endl; 239 return -1; 240 } 241 } 242 } 243 else 244 { 245 bool closeFlag(false); 246 247 while (true) 248 { 249 char recvBuf[10]; 250 251 int len(-1); 252 len = recv(retEvents[i].data.fd, recvBuf, sizeof(char[10]), 0); 253 if (-1 == len) 254 { 255 if (EAGAIN == errno) // 读完了 256 { 257 break; 258 } 259 closeFlag = true; 260 } 261 else if (0 == len) 262 { 263 closeFlag = true; 264 break; 265 } 266 267 write(1, recvBuf, len); 268 } 269 270 if(closeFlag) 271 { 272 cout << "close connectSocket Fd: " << retEvents[i].data.fd << endl; 273 close(retEvents[i].data.fd); 274 } 275 } 276 } 277 } 278 279 close(listenSocket); 280 281 return 0; 282 }