您的位置:首页 > 其它

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: