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 }

 

posted @ 2016-02-04 14:47  挨踢淫才  阅读(292)  评论(0编辑  收藏  举报