三组函数
(1)创建内核事件表
只是给内核一个提示,事件表需要多大;
返回值:内核事件表的文件描述符,可以理解为事件表红黑树的根;
(2)对内核事件表的增删改操作
注意epoll_event的结构;
(3)等待事件发生
第二个参数为已经就绪有事件发生的文件描述符集合**(与poll的区别就在此,poll只返回个数)**
poll和epoll的区别
代码epoll的使用
1 #include"wrap.h"
2 #include<errno.h>
3 #include<sys/epoll.h>
4 #define MAX_EVENT_NUM 1024
5 #define BUFF_SIZE 64
6
7 void delfd (int epollfd ,int fd)
8 {
9 struct epoll_event event;
10 event.events = EPOLLIN;
11 event.data.fd = fd;
12
13 epoll_ctl(epollfd,EPOLL_CTL_DEL,fd,&event);
14 }
15 void addfd(int epollfd , int fd)//fd做成结构体才能加入事件表
16 {
17 struct epoll_event event;
18 event.events = EPOLLIN;
19 event.data.fd = fd;
20
21 epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,&event);
22 }
23 int main(int argc , char * argv[])
24 {
25 if(argc < 2 )
26 {
27 printf("输入IP和端口\neg:./a.out 127.0.0.2 8000\n");
28 exit(1);
29 }
30 const char * ip = argv[1];
31 int port = atoi(argv[2]);
32 struct sockaddr_in saddr,caddr;
33
34 int sfd = Socket(AF_INET,SOCK_STREAM,0);
35
36 bzero(&saddr,sizeof(saddr));
37 saddr.sin_family = AF_INET;
38 saddr.sin_port = htons(port);
39 inet_pton(AF_INET,ip ,&saddr.sin_addr.s_addr);
40 Bind(sfd,(struct sockaddr*)&saddr,sizeof(saddr));
41
42 Listen(sfd,5);
43
44 int epollfd = epoll_create(5);//创建epoll事件表的期望大小,返回事件表的根,即红黑树的根;
45 if(epollfd ==-1 )
46 perr_exit("epoll_crete error");
47
48 addfd(epollfd , sfd);//封装函数,将监听socket加入epoll事件表;
49
50 struct epoll_event events[MAX_EVENT_NUM];//定义就绪事件容器;
51 while(1)
52 {
53 int ret = epoll_wait(epollfd,events,MAX_EVENT_NUM,-1);
54 if(ret < 0)
55 perr_exit("epoll-wait error");
56 int i;
57 for(i=0; i < ret ; ++i)
58 {
59 if(!events[i].events & EPOLLIN)//只关注读事件
60 continue;
61
62 if(events[i].data.fd == sfd )//监听事件sfd分一类处理,接受客户端;
63 {
64 socklen_t len = sizeof(caddr);
65 int cfd = Accept(sfd,(struct sockaddr *)&caddr,&len);
66 char str[64];
67 printf("client cfd ip =%s port=%d\n",inet_ntop(AF_INET,&caddr.sin_addr.s_addr,
68 str,64),ntohs(caddr.sin_port));
69 addfd(epollfd, cfd);//客户端放入监听事件表中epoll来监听;
70 }
71 else//其他客户端cfd事件分一类处理,读写数据
72 {
73 int sockfd = events[i].data.fd;//记录一下cfd方便使用;
74 char buff[BUFF_SIZE];
75 memset(buff,'\0',BUFF_SIZE);
76 int n = recv(sockfd,buff,BUFF_SIZE-1,0);
77 if(n == 0)//对方关闭
78 {
79 printf("client %d closing...\n",sockfd);
80 delfd(epollfd,sockfd);
81 continue;
82 }
83 if(n < 0)//接受数据出错
84 {
85 perror("client error");
86 delfd(epollfd,sockfd);
87 continue;
88 }
89 else//数据转化,并且发送数据
90 {
91 int j=0;
92 for(j=0;j<n;++j)
93 buff[j]=toupper(buff[j]);
94 int n =send(sockfd,buff,BUFF_SIZE-1,0);
95 if( n<0)
96 perror("send error");
97 }
98
99 }
100
101 }
102 }
103
104
105 return 0;
106 }
更多有关epoll的知识
惊群现象:https://zhuanlan.zhihu.com/p/385410196
Linux 惊群效应之 Nginx 解决方案:https://zhuanlan.zhihu.com/p/51251700