epoll案例
2016-02-04 14:47
267 查看
#include <stdio.h> #include <string.h> #include <errno.h> #include <iostream> #include <sys/socket.h> #include <netdb.h> #include <arpa/inet.h> #include <fcntl.h> #include <unistd.h> #include <sys/epoll.h> #define MAX_EVENTS 1024 using namespace std; static int setSocketNonBlock(const int socketFd) { int ret(0); int flags = fcntl(socketFd, F_GETFL, 0); if (-1 == flags) { cerr << "fcntl error" << endl; return -1; } flags |= O_NONBLOCK; ret = fcntl(socketFd, F_SETFL, flags); if (-1 == ret) { cerr << "fcntl error" << endl; return -1; } return 0; } static int setSocketLingerDisable(const int socketFd) { int ret(0); struct linger lingerVal; lingerVal.l_onoff = 1; lingerVal.l_linger = 0; ret = setsockopt(socketFd, SOL_SOCKET, SO_LINGER, &lingerVal, sizeof(struct linger)); if (0 != ret) { cerr << "setsockopt" << endl; return -1; } return 0; } static int create_and_bind() { int ret(0); struct addrinfo hints; struct addrinfo * retAddr, * retNext; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; hints.ai_flags = AI_PASSIVE; ret = getaddrinfo(NULL, "8090", &hints, &retAddr); if (0 != ret) { cerr << "getaddrinfo" << endl; return -1; } int listenSocket(-1); for (retNext = retAddr; retNext != NULL; retNext = retNext->ai_next) { // char ipBuf[1024]; // switch(retNext->ai_family) // { // case AF_INET: // inet_ntop(AF_INET, &((struct sockaddr_in *)(retNext->ai_addr))->sin_addr, ipBuf, sizeof(char[1024])); // break; // case AF_INET6: // inet_ntop(AF_INET6, &((struct sockaddr_in6 *)(retNext->ai_addr))->sin6_addr, ipBuf, sizeof(char[1024])); // break; // } // cout << "ipBuf: " << ipBuf << endl; listenSocket = socket(retNext->ai_family, retNext->ai_socktype, retNext->ai_protocol); if (-1 == listenSocket) { cerr << "socket error" << endl; continue; } ret = bind(listenSocket, retNext->ai_addr, retNext->ai_addrlen); if (0 != ret) { cerr << " bind error" << endl; close(listenSocket); continue; } break; // 已成功生成并绑定监听socket, 退出for遍历 } freeaddrinfo(retAddr); if (NULL == retNext) { cerr << "create_and_bind error" << endl; return 1; } return listenSocket; } int main(int argc, char **argv) { int ret(0); int listenSocket(-1); listenSocket = create_and_bind(); if (-1 == listenSocket) { return -1; } ret = setSocketNonBlock(listenSocket); if (0 != ret) { return -1; } ret = setSocketLingerDisable(listenSocket); if (0 != ret) { return -1; } ret = listen(listenSocket, 10); if (0 != ret) { cerr << "listen error" << endl; return -1; } int epollFd(-1); epollFd = epoll_create1(0); if (-1 == epollFd) { cerr << "epoll_create1 error" << endl; return -1; } // 监听socket注册到epollFd中管理 struct epoll_event event; event.data.fd = listenSocket; event.events = EPOLLET | EPOLLIN; ret = epoll_ctl(epollFd, EPOLL_CTL_ADD, listenSocket, &event); if (0 != ret) { cerr << "epoll_ctl error" << endl; return -1; } struct epoll_event retEvents[MAX_EVENTS]; bool done(false); int retEventsCnt(0); while (!done) { retEventsCnt = epoll_wait(epollFd, retEvents, MAX_EVENTS, 1000); cout << "retEventCnt: " << retEventsCnt << endl; for (int i = 0; i < retEventsCnt; ++i) { if ((retEvents[i].events & EPOLLERR) || (retEvents[i].events & EPOLLHUP) || !(retEvents[i].events & EPOLLIN)) { cerr << "socketFd: " << retEvents[i].data.fd << " error" << endl; close(retEvents[i].data.fd); continue; } else if (listenSocket == retEvents[i].data.fd) { while (true) { struct sockaddr remoteSockAddr; socklen_t len = sizeof(struct sockaddr); int connectSocket(-1); connectSocket = accept(listenSocket, &remoteSockAddr, &len); if (-1 == connectSocket) { if (EAGAIN == errno) { break; } else { cerr << "accept error" << endl; continue; } } char hostStr[100]; char serviceStr[100]; ret = getnameinfo(&remoteSockAddr, sizeof(struct sockaddr), hostStr, sizeof(char[100]), serviceStr, sizeof(char[100]), 0); if (0 == ret) { printf("client info: [connectSocket: %d, host: %s, port: %s]\n", connectSocket, hostStr, serviceStr); } ret = setSocketNonBlock(connectSocket); if (0 != ret) { return -1; } ret = setSocketLingerDisable(connectSocket); if (0 != ret) { return -1; } event.data.fd = connectSocket; event.events = EPOLLET | EPOLLIN; ret = epoll_ctl(epollFd, EPOLL_CTL_ADD, connectSocket, &event); if (0 != ret) { cerr << "epoll_ctl error" << endl; return -1; } } } else { bool closeFlag(false); while (true) { char recvBuf[10]; int len(-1); len = recv(retEvents[i].data.fd, recvBuf, sizeof(char[10]), 0); if (-1 == len) { if (EAGAIN == errno) // 读完了 { break; } closeFlag = true; } else if (0 == len) { closeFlag = true; break; } write(1, recvBuf, len); } if(closeFlag) { cout << "close connectSocket Fd: " << retEvents[i].data.fd << endl; close(retEvents[i].data.fd); } } } } close(listenSocket); return 0; }
相关文章推荐
- 经济学--第一讲
- cookie
- 打印机 Fax 所需的驱动程序 Microsoft Shared Fax Driver 未知
- AbstractQueuedSynchronizer
- 单向链表
- oracleXE(oracle学习版)在windows的安装配置
- CDOJ 1270 Playfair(模拟)
- native2ascii 在 Mac终端的转码
- Java经典用法总结(二)
- docker升级方法
- 我的博客即将入驻“云栖社区”,诚邀技术同仁一同入驻。
- C中函数传递参数原理:值传递, 指针传递?
- redis的主从切换的两种方式
- Java实现Socket之WhoisClient
- 关于Activity被回收
- 适合新手动手实践的PHP搭配mysql的小项目--02实现注册页面
- Grafana-Zabbix扩展安装
- symfony2中运行周期内执行的回调函数
- Android百度地图
- java注解处理器