Cashey1991的专栏

epoll极简介绍

关于epoll的详细介绍,已经有较多文章可以参考,例如这篇文章介绍就比较详细:

epoll编程的接口:

使用epoll时有如下应该注意的地方:

如下代码是使用epoll实现的多路复用TCP的简单Server及其测试客户端:

/****************************************************************************** * 文件名称:TestEpoll.cpp * 文件描述:Epoll测试服务器端 * 创建日期:2015-04-09 * 作 者:casheywen ******************************************************************************/;CreateListenFd(const char *pszIP, uint16_t usPort){struct sockaddr_in stAddr;stAddr.sin_family = AF_INET;stAddr.sin_port = htons(usPort);stAddr.sin_addr.s_addr = inet_addr(pszIP);socklen_t nAddrLen = sizeof(struct sockaddr_in);int iFd = socket(AF_INET, SOCK_STREAM, 0);if (iFd < 0){LOG_ERR(“create socket fail: %s”, strerror(errno));return -1;}if (0 > bind(iFd, (struct sockaddr *)&stAddr, nAddrLen)){LOG_ERR(“bind fail: %s”, strerror(errno));return -1;}if (0 > listen(iFd, 64)){LOG_ERR(“listen fail: %s”, strerror(errno));return -1;}LOG_INFO(“Listening: %s:%hu, fd=%d”, pszIP, usPort, iFd);return iFd;}bool SetSockNonBlock(int iSockfd){int iRet = fcntl(iSockfd, F_GETFL, 0);if (-1 == iRet){return false;}if (-1 == fcntl(iSockfd, F_SETFL, iRet | O_NONBLOCK)){return false;}return true;}int main(){int iEpollFd = epoll_create(100); // 100为预估需要epoll的fd数量if (iEpollFd < 0){LOG_ERR(“epoll_create fail: %s”);return 1;}int iListenFd = CreateListenFd(“0.0.0.0”, 12333);if (iListenFd < 0){LOG_ERR(“CreateListenFd Fail”);return 1;}if (!SetSockNonBlock(iListenFd)) // 确保socket为非阻塞状态{LOG_ERR(“SetSockNonBlock Fail: %s”, strerror(errno));return 1;}struct epoll_event ev, events[20];ev.events = EPOLLIN;ev.data.fd = iListenFd;// 将监听的socket加入epollint iRet = epoll_ctl(iEpollFd, EPOLL_CTL_ADD, iListenFd, &ev);if (iRet < 0){LOG_ERR(“epoll_ctl fail: %s”, strerror(errno));return 1;}while (true){iRet = epoll_wait(iEpollFd, events, sizeof(events), -1); // 最后的-1表示超时时间无穷大if (iRet < 0){if (errno == EINTR){LOG_ERR(“Interrupted, quit.”);}else{LOG_ERR(“epoll_wait fail: %s”, strerror(errno));}return 1;}int iEvents = iRet;for (int i = 0; i < iEvents; i++){// 对于监听状态中的套接字,,可读意味着有新的连接if (events[i].data.fd == iListenFd){struct sockaddr_in stClientAddr;socklen_t nAddrLen = sizeof(stClientAddr);memset(&stClientAddr, 0, sizeof(stClientAddr));int iClientFd = accept(iListenFd, (struct sockaddr *)&stClientAddr, &nAddrLen);if (iClientFd < 0){LOG_ERR(“accept fail: %s”, strerror(errno));return 1;}if (!SetSockNonBlock(iClientFd)) // 将新连接的套接字设置为非阻塞{LOG_ERR(“SetSockNonBlock Fail: fd=%d %s”, iClientFd, strerror(errno));return 1;}LOG_INFO(“Connected:%s:%hu, fd=%d”, inet_ntoa(stClientAddr.sin_addr), htons(stClientAddr.sin_port), iClientFd);ev.events = EPOLLIN;ev.data.fd = iClientFd;// 将连接的fd加入epollint iRet = epoll_ctl(iEpollFd, EPOLL_CTL_ADD, iClientFd, &ev);if (iRet < 0){LOG_ERR(“epoll_ctl fail: %s”, strerror(errno));return 1;}}else // 对于客户端连接可读的情况{int iClientFd = events[i].data.fd;static char s_acBuf[10 * 1024] = {0};int iTotal = 0;do{iRet = recv(iClientFd, &s_acBuf[iTotal], sizeof(s_acBuf) – iTotal, 0);if (iRet > 0){iTotal += iRet;}else if (iRet < 0 && errno == EAGAIN){LOG_INFO(“Total: %d Bytes, [%s]”, iTotal, s_acBuf);break;}else{if (iRet == 0) // 连接已经断开{LOG_INFO(“Disconnected: fd=%d”, iClientFd);}else // iRet < 0 出现错误{LOG_INFO(“recv fail: fd=%d %s”, iClientFd, strerror(errno));}// 将出错或断开连接的fd从epoll中去掉int iRet = epoll_ctl(iEpollFd, EPOLL_CTL_DEL, iClientFd, NULL);if (iRet < 0){LOG_ERR(“epoll_ctl fail: %s”, strerror(errno));return 1;}close(iClientFd);break;}} while (iTotal < sizeof(s_acBuf));}}}return 0;}/****************************************************************************** * 文件名称:TcpClient.cpp * 文件描述:Epoll测试客户端 * 创建日期:2015-04-09 * 作 者:casheywen ******************************************************************************/;SigPipeHandler(int iSigno){LOG_ERR(“SigPipe received”);exit(1);}bool ConnectTcpSocket(int iFd, const char *pszIP, uint16_t usPort){struct sockaddr_in stAddr;memset(&stAddr, 0, sizeof(stAddr));stAddr.sin_family = AF_INET;inet_aton(pszIP, &stAddr.sin_addr);stAddr.sin_port = htons(usPort);int iRet = connect(iFd, (struct sockaddr *)&stAddr, sizeof(stAddr));if (iRet < 0){LOG_ERR(“Connect Fail: %s”, strerror(errno));return false;}return true;}int main(){int iFd = socket(AF_INET, SOCK_STREAM, 0);if (iFd < 0){LOG_ERR(“Create Socket Fail: %s”, strerror(errno));return 1;}if (!ConnectTcpSocket(iFd, “127.0.0.1”, 12333)){LOG_ERR(“ConnectUnixSocket Fail”);return 1;}LOG_INFO(“Connect Success”);if (SIG_ERR == signal(SIGPIPE, SigPipeHandler)) // 当连接中断时调用write函数会收到SIGPIPE信号{LOG_ERR(“Signal Fail: %s”, strerror(errno));return 1;}char szContent[4096];ssize_t nWrite = 0;while (cin >> szContent){nWrite = write(iFd, szContent, strlen(szContent));if (nWrite < 0){LOG_ERR(“write Fail: %s”, strerror(errno));return 1;}}return 0;}

只有不断找寻机会的人才会及时把握机会。

Cashey1991的专栏

相关文章:

你感兴趣的文章:

标签云: