Epoll LT和ET模式

关于epoll解说请参考:

点击打开链接

下面是使用实例,也可以参考man epoll Ubuntu上的实例

#define BUFFSIZE 1024
#define PORT 5588
using namespace std;

#define ERR_EXIT(a) do \
{ \
	printf("%s", a); \
} while (0);

typedef vector<struct epoll_event> EventList;

template<typename T>
void log(T msg)
{
	cout<<msg<<endl;
}

void activate_nonblock(int fd)  
{  
    int ret;  
    int flags=fcntl(fd,F_GETFL);  
    if(flags == -1)  
    {  
        ERR_EXIT("fcntl");      
    }  
    flags |= O_NONBLOCK;  
    ret = fcntl(fd,F_SETFL,flags);  
    if(ret ==-1)  
    {  
        ERR_EXIT("fcntl");  
    }  
      
} 

int initSock()
{
	int fd = socket(AF_INET, SOCK_STREAM, 0);
	struct sockaddr_in sockaddr_t;
	memset(&sockaddr_t, 0, sizeof(sockaddr_t));
	sockaddr_t.sin_family = AF_INET;
	sockaddr_t.sin_port = htons(PORT);
	sockaddr_t.sin_addr.s_addr = htonl(INADDR_ANY);

	/*设置为非阻塞*/
	// int flags = fcntl(fd, F_GETFL, 0);
	// fcntl(fd, F_SETFL, flags|O_NONBLOCK);

	//设置地址重复利用
	int on = 1;
	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
	{
		log("setsockopt");
	}
	
	if (bind(fd, (struct sockaddr*)&sockaddr_t, sizeof(sockaddr_t)) < 0 )
	{
		log("bind is failed");
		return -1;
	}

	if(listen(fd, SOMAXCONN) < 0)
	{
		log("listen is failed");
		return -1;
	}
	return fd;
}


int acceptPool(int fd)
{
	int acceptfd;
	
	struct sockaddr_in clientAddr;
	socklen_t len = sizeof(clientAddr);

	char readbuff[BUFFSIZE];

	EventList events(10);
	struct epoll_event ev;
	int epollfd = epoll_create1(EPOLL_CLOEXEC);
	ev.events = EPOLLIN;//设置关注事件
	ev.data.fd = fd;

	if(epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) < 0)
	{
		log("epoll_ctl is errno");
		exit(EXIT_FAILURE);
	}

	int retVal = 0;
	while(1)
	{
		retVal = epoll_wait(epollfd, &*events.begin(), static_cast<int>(events.size()), -1);
		if (retVal < 0 && errno == EINTR)
		{

			continue;
		}
		else if (retVal < 0)
		{
			log("epoll_wait is errno");
			return -1;
		}
		if (events.size() == retVal)
		{
			events.resize(events.size() * 2);
		}
		
		cout<<"things size is :"<<events.size()<<endl;
		for (int i = 0; i < events.size(); ++i)
		{
			if (events[i].data.fd == fd)
			{
				acceptfd = accept(events[i].data.fd, (struct sockaddr*)&clientAddr,&len);
				if (acceptfd < 0)
				{
					log("accept is errno");
					return -1;
				}
				activate_nonblock(acceptfd);
				ev.data.fd = acceptfd;
				ev.events = EPOLLIN; //设置关注事件
				epoll_ctl(epollfd, EPOLL_CTL_ADD, acceptfd, &ev); //将新的连接添加到关注的集合
				log("have a client connect");
			}
			else if (events[i].events & EPOLLIN)
			{
				memset(readbuff, 0, sizeof(readbuff));
				int ret = read(events[i].data.fd, readbuff, sizeof(readbuff));
				if (ret < 0)
				{
					log("read erron");
					break;
				}
				else if (ret == 0)
				{
					log("close a client");
					close(events[i].data.fd);
					epoll_ctl(epollfd, EPOLL_CTL_DEL, events[i].data.fd, &events[i]);
					continue;
				}
				log(readbuff);
				write(events[i].data.fd, readbuff, strlen(readbuff));
			}
		}

	}

	return 0;
}

int main(int argc, char const *argv[])
{
	int fd = initSock();
	acceptPool(fd);
	return 0;
}

epoll LT 模式:水平触发,当内核缓冲区为空时(write)或为满时(read)触发



epoll ET模式:边缘触发,当内核缓冲区为由满到空时(write)或为由空到满时(read)触发


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值