1, Epoll ()
Epoll () is a Linux-specific I/O multiplexing function, and its implementation differs greatly from the use and select (), poll ().
Epoll () uses a set of functions to accomplish a task, not a single function, and secondly, epoll () places the file description in the kernel event table with an additional file descriptor that identifies the unique event table in the kernel.
The API to use:
int epoll_create (int size);
int epoll_ctl (int epfd, int op, int fd, struct epoll_event *event);
Structure information you need to use:
typedef union Epoll_data {void *ptr; int FD; In general, this is the file descriptor uint32_t u32; uint64_t U64;} Epoll_data_t;struct epoll_event {uint32_t events; /* Epoll Events */epoll_data_t data; /* USER Data variable */};
int epoll_wait (int epfd, struct epoll_event *events, int maxevents, int timeout);
2, Epoll_wait ()
Key: The core understanding of the epoll_wait () function
(1), return value: The number of ready clients in the event table;
(2), parameters events: Put the information of the ready client in the event table into the events array.
3. The core idea of Epoll ()
is to create a kernel event table that holds the sockets and current events of the listening client, using the epoll_wait () function to find a ready socket, and finally adding, deleting, and modifying the use of the Epoll_ctl () function; Of course, there are a number of macros used in conjunction with it;
3. Code implementation
(1), utili.h
#include <unistd.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys /socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <assert.h> #include <sys/ select.h> #define SERVER_IP "127.0.0.1" #define Server_port 8787#define listen_queue 5#define SIZE 10#define buffer_ SIZE 256#include<poll.h> #define OPEN_MAX 1000#include<sys/epoll.h> #define FDSIZE 1000#define EPOLLEVENTS 100
(2), ser.c
#include ". /utili.h "Static int socket_bind (const char *ip, int port) { int listenfd = socket (af_inet, sock_stream, 0); struct sockaddr_in addrSer; addrSer.sin_family = AF_INET; &NBSP;&NBSP;//ADDRSER.SIN_ADDR.S_ADDR&NBSP;=&NBSP;INET_ADDR (IP); inet_pton (AF_INET, &NBSP;IP,&NBSP;&ADDRSER.SIN_ADDR); addrser.sin_port = htons (port); bind (listenfd, (struct sockaddr*) &addrser, sizeof (STRUCT&NBSP;SOCKADDR)); &NBSP;&NBSP;&NBSP;&NBSP;RETURN&NBSP;LISTENFD;} Static void add_event (int epollfd, int fd, int state) { struct epoll_event ev; ev.events = state; ev.data.fd = fd; epoll_ctl (Epollfd, epoLl_ctl_add, fd, &ev);} Static void delete_event (int epollfd, int fd, int state) { struct epoll_event ev; ev.events = state; ev.data.fd = fd; epoll_ctl (epollfd, epoll_ctl_del, fd, &ev);} Static void modify_event (int epollfd, int fd, int state) { struct epoll_event ev; ev.events = state; ev.data.fd = fd; epoll_ctl (epollfd, epoll_ctl_mod, fd, &ev);} Static void handle_accept (INT&NBSP;EPOLLFD,&NBSP;INT&NBSP;LISTENFD) { int clifd; struct sockaddr_in addrcli; socklen_t len = sizeof (STRUCT&NBSP;SOCKADDR); clifD = accept (listenfd, (struct sockaddr*) &addrcli, &len); if (clifd != -1) { add_event (EPOLLFD,&NBSP;CLIFD, epollin); }}static void do_read (int epollfd, int FD,&NBSP;CHAR&NBSP;*BUF) { int nread = read (fd, buf, BUFFER_ SIZE); if (nread == -1) { close ( FD); delete_event (Epollfd, fd, epollin); }else{ printf ("read msg:>%s\n", buf); modify_event (epollfd, fd, epollout); }}static void do_write (INT&NBSP;EPOLLFD,&NBSP;INT&NBSP;FD,&NBSP;CHAR&NBSP;*BUF) { int nwritE = write (Fd, buf, strlen (BUF) +1); if (nwrite == -1) { close (FD); Delete_event (epollfd, fd, epollout); } else{ modify_event (Epollfd, fd , epollin); } memset (buf, 0, buffer_size);} Static void handle_events (Int epollfd, struct epoll_event *events, int num, int listenfd, char *buf ) { int i; int fd; for (i=0; i<num; ++i) { fd = eventS[i].data.fd; if (FD==LISTENFD) && (Events[i] . Events&epollin) //into three states according to their results handle_accept (EPOLLFD,&NBSP;LISTENFD); //application and Server connection else if (Events[i].events & epollin) do_read (EPOLLFD,&NBSP;FD,&NBSP;BUF); //read-only else if (events[i].events & epollout) do_write (EPOLLFD,&NBSP;FD, &NBSP;BUF); //write }}static void do_epoll (INT&NBSP;LISTENFD) { int ret; char buffer[BUFFER_SIZE]; Struct epoll_event events[epollevents]; int epollfd = epoll_create (FDSIZE); add_event (Epollfd, listenfd, epollin); for (;;) { //select poll ret = epoll_wait (epollfd, events, epollevents, -1); handle_events (Epollfd, events, ret, listenfd, buffer); } close (EPOLLFD);} Int main (void) { int listenfd; listenfd = Socket_bind (Server_ip, server_port); listen (Listenfd, listen_queue); do_epoll (LISTENFD); return 0;}
(3), CLI.C
#include ". /utili.h "Static void add_event (int epollfd, int fd, int state) { struct epoll_event ev; ev.events = state; ev.data.fd = fd; epoll_ctl (EPOLLFD,&NBSP;EPOLL_CTL_ADD,&NBSP;FD, &ev);} Static void delete_event (int epollfd, int fd, int state) { struct epoll_event ev; ev.events = state; ev.data.fd = fd; epoll_ctl (EPOLLFD,&NBSP;EPOLL_CTL_DEL,&NBSP;FD, &ev);} Static void modify_event (int epollfd, int fd, int state) { struct epoll_event ev; ev.events = state; ev.data.fd = fd; epoll_ctl (EPOLLFD, epoll_ctl_mod, fd, &ev);} Static void do_read (int epollfd, int fd, int sockfd, char * BUF) { int nread = read (fd, buf, buffer_size); if (nread == -1) { close (FD); delete_event (Epollfd, fd, epollin); }else{ if (Fd == stdin_fileno) add_event (Epollfd, fd, epollin); else{ delete_event (Epollfd, fd, epollin); add_event (epollfd, stdout_fileno, epollout); } } printf ("Ser :>%s", buf) ;} Static void do_write (INT&NBSP;EPOLLFD,&NBSP;INT&NBSP;FD,&NBSP;INT&NBSP;SOCKFD,&NBSP;CHAR&NBSP;*BUF) { int nwrite = write (Fd, buf, strlen (BUF) +1); if (nwrite == -1) { perror ("write"); close (FD); }else{ if (Fd == stdout_fileno) { delete_event (epollfd, fd, epollout); }else{ modify_event (EPOLLFD, fd, epollin); } } &nBsp; memset (buf, 0, buffer_size);} Static void handle_events (Int epollfd, struct epoll_event *events, int num, &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;INT&NBSP;SOCKFD,&NBSP;CHAR&NBSP;*BUF) { int i; int fd; for (i=0; i <num; ++i) { fd = events[i].data.fd; if (Events[i].events & epollin) do_read (EPOLLFD,&NBSP;FD,&NBSP;SOCKFD,&NBSP;BUF); else if (EVENTS[I].EVENTS,&NBSP;FD,&NBSP;SOCKFD,&NBSP;BUF) do_write (EPOLLFD,&NBSP;FD, sockfd, buf); }}static void handle_connection (INT&NBSP;SOCKFD) { struct epoll_event events[EPOLLEVENTS]; int Epollfd = epoll_create (fdsize); add_event (epollfd, stdin_fileno, Epollin); int ret; char buffer[buffer_size]; for (;;) { ret = epoll_wait (epollfd, events, EPOLLEVENTS,&NBSP;-1); handle_events (Epollfd, events, ret, sockfd, buffer); } close (EPOLLFD);} Int main (void) { int sockfd = socket (Af_inet, sock_stream, &NBSP;0); struct sockaddr_in addrser; addrser.sin_ Family = af_inet; addrser.sin_port = htons (server_port); addrser.sin_ ADDR.S_ADDR&NBSP;=&NBSP;INET_ADDR (SERVER_IP); connect (sockfd, (struct sockaddr*) &addrser, sizeof (struct sockaddr)); handle_connection (SOCKFD); close (SOCKFD); return 0;}
Run results
Server-side is waiting for the use of the client;
Client 1
650) this.width=650; "Src=" Http://s3.51cto.com/wyfs02/M01/88/17/wKioL1fpqXei35d_AAAZ3YfRI20994.png-wh_500x0-wm_3 -wmp_4-s_1441849682.png "title=" Qq20160927070409.png "alt=" Wkiol1fpqxei35d_aaaz3yfri20994.png-wh_50 "/>
Client 2
650) this.width=650; "Src=" Http://s3.51cto.com/wyfs02/M02/88/17/wKioL1fpqbCTD-LIAAAW7mAZK28187.png-wh_500x0-wm_3 -wmp_4-s_1055467077.png "title=" Qq20160927070510.png "alt=" Wkiol1fpqbctd-liaaaw7mazk28187.png-wh_50 "/>
Using the Epoll () function, the efficiency is more efficient without polling each socket;
This article is from the "11586096" blog, please be sure to keep this source http://11596096.blog.51cto.com/11586096/1856827
Linux I/O multiplexing--epoll