您的位置:首页 > 运维架构 > Linux

Linux c++ epoll 模型demo

2017-07-15 22:13 323 查看
部分代码复用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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息