Linux c++ epoll 模型demo

来源:互联网 发布:linux telnet 安装 编辑:程序博客网 时间:2024/06/06 04:28

部分代码复用select的代码

核心代码如下

#include <unistd.h>#include <sys/types.h>#include <fcntl.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <signal.h>#include <fcntl.h>#include <sys/wait.h>#include <sys/epoll.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <string.h>#include <vector>#include <algorithm>#include <iostream>#include "socket.h"typedef std::vector<struct epoll_event> EPOLL_FD_VECTOR;int main(void){    InitErrDeal();    int s32ServerSocket = -1;     InitServerSocket(s32ServerSocket);    std::vector<int> clients;    int s32EpollFd;    s32EpollFd = epoll_create1(EPOLL_CLOEXEC);    struct epoll_event stEvent;    stEvent.data.fd = s32ServerSocket;    stEvent.events = EPOLLIN;/*水平触发, | EPOLLET边沿触发*/    epoll_ctl(s32EpollFd, EPOLL_CTL_ADD, s32ServerSocket, &stEvent);    EPOLL_FD_VECTOR vecEpollEvents(16);    int s32ActiveFd;    int s32ActiveFdNum;    while (1)    {        s32ActiveFdNum = epoll_wait(s32EpollFd, &*vecEpollEvents.begin(), static_cast<int>(vecEpollEvents.size()), -1);        if (s32ActiveFdNum > 0)        {            //一次性返回的事件队列满了,会分成多次返回            if ((size_t)s32ActiveFdNum == vecEpollEvents.size())            {                vecEpollEvents.resize(vecEpollEvents.size()*2);            }            for (int i = 0; i < s32ActiveFdNum; ++i)            {                if (vecEpollEvents[i].data.fd == s32ServerSocket)//有连接事件                {                    struct sockaddr_in stClientAddr;                    socklen_t Addrlen = sizeof(struct sockaddr_in);                    s32ActiveFd = ::accept4(s32ServerSocket, (struct sockaddr*)&stClientAddr,                            &Addrlen, SOCK_NONBLOCK | SOCK_CLOEXEC);                    if (s32ActiveFd == -1)                    {                        //进程打开描述符到达上限处理                        if (errno == EMFILE)                        {                            ERR_INFO_S stErrInfo;                            stErrInfo.enErrType = ERR_EMFILE;                            stErrInfo.pvUserData = (void *)&s32ActiveFd;                            ProcessErr(stErrInfo);                            continue;                        }                        else                        {                            SHOW_ERR("accept4 err!\n");                            continue;                        }                    }                    SHOW_SOCKADDR_INFO(stClientAddr);                    clients.push_back(s32ActiveFd);                    stEvent.data.fd = s32ActiveFd;                    stEvent.events = EPOLLIN;/* | EPOLLET*/                    epoll_ctl(s32EpollFd, EPOLL_CTL_ADD, s32ActiveFd, &stEvent);                }                else if (vecEpollEvents[i].events & EPOLLIN)//可读                {                     s32ActiveFd = vecEpollEvents[i].data.fd;                    char szContent[256]={0};                     int s32Ret = ::recv(s32ActiveFd, szContent, sizeof(szContent), 0);                     //使用read也可以                    if (s32Ret > 0)                     {                         szContent[s32Ret] = '\0';                         INFO_PRINT("recv %d:%s\n",s32Ret, szContent);                         ::send(s32ActiveFd, szContent, s32Ret, 0);                         //使用write也行                    }                     else //异常或关闭的                    {                         ::close(s32ActiveFd);                         stEvent = vecEpollEvents[i];                        epoll_ctl(s32EpollFd, EPOLL_CTL_DEL, s32ActiveFd, &stEvent);                        clients.erase(std::remove(clients.begin(), clients.end(), s32ActiveFd), clients.end());                        INFO_PRINT("close[%d]\n",s32ActiveFd);                    }                 }            }        }        //timeout        else if (s32ActiveFdNum == 0)        {            continue;        }        else        {            if (errno == EINTR)            {                continue;            }            SHOW_ERR("\n");            return FAILURE;        }    }    return SUCCESS;}