1 /*
2 头文件:#include<sys/epoll.h>
3 epoll是select/poll的进阶版,同样是内核监听客户端连接服务器请求的设置
4
5 原型:
6 创建epoll句柄
7 int epoll_create(int size);
8 size: 设置epoll的文件描述符数量
9 返回值:成功返回epoll句柄描述符;失败返回-1,设置errno
10 作用:建立红黑epoll树,返回的epoll文件描述符为所建epoll红黑树的根结点(也称为句柄)
11 eg:int epfd=epoll_create(10);
12 */
13
14 /*
15 头文件:#include<sys/epoll.h>
16 原型:
17 int epoll_ctl(int epfd,int op,int fd,struct epoll_event *event);
18 epfd: epoll的句柄
19 op: 控制选项
20 EPOLL_CTL_ADD:添加节点
21 EPOLL_CTL_MOD:修改节点
22 EPOLL_CTL_DEL:删除节点
23 fd: 选定需要操作的文件描述符
24 event:结构体
25 struct epoll_event{
26 uin32_t events;
27 epoll_data_t data;
28 };
29 events:
30 EPOLLIN 可读
31 EPOLLOUT 可写
32 EPOLLRDHUP
33 EPOLLPRI
34 EPOLLERR 异常
35 EPOLLHUP 对应的文件描述符被挂断
36 typedef union epoll_data{
37 void *ptr;
38 int fd;
39 uin32_t u32;
40 uint64_t u64;
41 }epoll_data_t;
42 返回值:成功返回0,失败返回-1,设置errno
43 作用:添加或删除监听的文件描述符
44 eg:
45 struct epoll_event myevent; 建立结构体
46 myevent.events=EPOLLIN; 设置可读事件
47 myevent.data.fd=fd; 设置文件描述符
48 epoll_ctl(epfd,EPOLL_CTL_ADD,fd,&myevent); 添加上面的结构体进入epoll红黑树
49 */
50
51 /*
52 头文件:#include<sys/epoll.h>
53 原型:
54 int epoll_wait(int epfd,struct epoll_event *events,int maxevents,int timeout);
55 events: 存储内核得到的事件的集合
56 maxevents: 限定events的大小
57 timeout: 监听时间 ; -1:阻塞 ; 0:立即返回,非阻塞 ; >0:指定的毫秒,阻塞
58 返回值:成功返回有多少文件描述等待连接,时间到时返回0,出错返回-1,设置errno
59 作用:等待监听的文件描述符满足条件
60 eg:
61 struct epoll_event evt[]; 定义结构体数组
62 epoll_wait(epfd,evt,sizeof(evt),(设置监听时间));
63 */
epoll使用:
64 void main(void)
65 {
66 int serv_sock,clie_sock,read_sock;
67 serv_sock=socket(AF_INET,SOCK_STREAM,0);
68 char buf[BUFSIZ];
69 int n,i;
70 struct sockaddr_in serv_sockaddr,clie_sockaddr;
71 socklen_t clie_sockaddr_len=sizeof(clie_sockaddr);
72 bzero(&clie_sockaddr,sizeof(clie_sockaddr));
73 bzero(&serv_sockaddr,sizeof(serv_sockaddr));
74 serv_sockaddr.sin_family=AF_INET;
75 serv_sockaddr.sin_port=htons(SERV_PORT);
76 serv_sockaddr.sin_addr.s_addr=htonl(INADDR_ANY);
77 //设置epfd根节点,event监听事件,events收集监听数组
78 int epfd,request;
79 struct epoll_event event, events[10];
80 epfd=epoll_create(10);
81 event.events=EPOLLIN;
82 event.data.fd=serv_sock;
83 //添加监听事件到epfd节点
84 epoll_ctl(epfd,EPOLL_CTL_ADD,serv_sock,&event);
85
86 bind(serv_sock,(struct sockaddr *)&serv_sockaddr,sizeof(serv_sockaddr));
87 listen(serv_sock,128);
88
89 while(1){//内核监听serv_sock事件
90 request=epoll_wati(epfd,events,sizeof(events),-1);
91 if(request==-1){
92 perror("epoll_wait error\n");
93 }
94 for(i=0;i<request;i++) {
95 if(!events[i].events & EPOLLIN)//如果不是可读事件回到for继续遍历
96 continue;
97 if(events[i].data.fd==serv_sock){
98 clie_sock=acccept(serv_sock,(struct sockaddr *)&clie_sockaddr,&clie_so ckaddr_len);
99 struct epoll_event tep;
100 tep.events=EPOLLIN;
101 tep.data.fd=clie_sock;
102 epoll_ctl(epfd,EPOLL_CTL_ADD,clie_sock,&tep);
103 }
104 else {
105 read_sock=events.data.fd;
106 n=read(read_sock,buf,sizeof(buf));
107 if(n==0){
108 epoll_ctl(epfd,EPOLL_CTLDEL,read_sock,NULL);
109 close(read_sock);
110
111 }
112 else{
113 for(i=0;i<n;i++)
114 buf[i]=toupper(buf[i]);
115 write(read_sock,buf,n);
116 }
117 }
118 }
119 }
120 }
本文深入讲解epoll的工作原理及使用方法,包括epoll_create、epoll_ctl和epoll_wait等核心函数的应用,并通过实例演示了如何利用epoll实现高效的网络服务器。
1109

被折叠的 条评论
为什么被折叠?



