epoll使用实例

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/tcp.h>
#include <sys/select.h>
#include <poll.h>
#include <netdb.h>
#include <limits.h>
#include <sys/epoll.h>


#define ip "127.0.0.1"
#define port 8888
#define MAXSIZE 3


int main(int argc, char* argv[])
{
	int afd, sfd;
	struct sockaddr_in servaddr;

	//创建socket文件描述符
	sfd = socket(AF_INET, SOCK_STREAM, 0);
	if(sfd == -1)
	{
		perror("sfd == -1");
		exit(1);
	}

	//防止端口复用
	int reuse = 1 ;
	setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void*)&reuse, sizeof(reuse));

	//初始化socket
	
	memset(&servaddr, 0, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(port) ;
	servaddr.sin_addr.s_addr = inet_addr(ip);

	//绑定套接字
	if(bind(sfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1)
	{
		perror("bind error");
		exit(1);
	}

	//监听套接字
	if(listen(sfd, 5) == -1)
	{
		perror("listen error");
		exit(1);
	}

	int epfd = epoll_create(MAXSIZE);
	if(epfd == -1)
	{
		perror("epoll_create");
		exit(1);
	}

	struct epoll_event ev;
	ev.data.fd = sfd;
	ev.events = EPOLLIN;

	if(epoll_ctl(epfd, EPOLL_CTL_ADD, sfd, &ev) == -1)
	{
		perror("epoll_ctl");
		exit(1);
	} 

	int nfd;
	struct epoll_event evlist[MAXSIZE];
	//evlist = &ev;
	while(1)
	{
		nfd = epoll_wait(epfd, evlist, MAXSIZE, 0);
		if(nfd == -1)
		{
			perror("epoll_wait");
			exit(1);
		}

		for(int i = 0; i < nfd; ++i)
		{
			if(evlist[i].events & EPOLLIN)
			{
				if(evlist[i].data.fd == sfd)
				{
					afd = accept(sfd, NULL, NULL);
					ev.data.fd = afd;
					ev.events = EPOLLIN;
					if(epoll_ctl(epfd, EPOLL_CTL_ADD, afd, &ev) == -1)
					{
						perror("epoll_ctl");
						exit(1);
					} 
				}else
				{
					int readn;
					char buf[10];
					memset(buf, 0, 10);
					if((readn = read(evlist[i].data.fd, buf, 10)) < 0)
					{
						perror("read error");
						exit(1);
					}
					if(readn == 0)
					{
						ev.data.fd = evlist[i].data.fd;
						ev.events = EPOLLIN;
						epoll_ctl(epfd, EPOLL_CTL_DEL, evlist[i].data.fd, &ev);
						close(evlist[i].data.fd);
					}else
					{
						printf("%s\n", buf);
					}
				}
			}
		}
	}
	close(epfd);
	close(sfd);
	return 0;
}

epoll有边界触发和水平触发两种方式,select/poll只有一种

et会把进来的连接和数据一次给你,如果你一次没有全部取完下次就不会给你了,lt只要这次没有被取走下次还能取到,et触发系统调用次数少

两者的区别:

比如说你从某宝下单买了几个东西,这几个东西分别由N个快递员分别给你送过来。在某一时刻,你开始等快递。
对于select/poll,就是你在睡觉的时候,收到一条短信“你有快递到了,取一下”,但不知道发送方是谁(但一定是那N个快递员中的某人/某几个人给你发的),所以你必须挨个给那N个快递员分别打个电话,问他们,是不是我的快递已经到了。
至于select/poll的区别,类似于你和快递员都分别有两个手机号,一个移动,一个联通,其区别就在于你用哪个手机号给他们打的问题。
对于epoll,是你收到那条短信的时候,看到了发送方的电话号码,你就可以直接给他打电话,问他在哪儿,你好去去快递。

还可以形象一点

select/poll
饭店服务员(内核)告诉饭店老板(用户程序):”现在有客人结账“
但是这个服务员没人明确告诉老板,哪几桌的客人结帐。老板得自儿一个一个桌子去问:请问是你要结帐?
epoll
饭店服务员(内核)告诉饭店老板(用户程序):”1,2,5号客人结账“
老板就可以直接去1,2,5号桌收钱了


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值