The difference between using poll and Epoll is mainly:
The poll can reload the FD array every time, but Epoll's FD is added at the beginning and cannot be re-added every time.
This strategy is then used:
Epoll In addition to listenfd the first time to listen to the Read event, the other customer FD joins Epoll, the listener event is empty.
Then use Epoll_ctl to reset the FD listener event before each epoll_wait.
So this part of the code is as follows:
//Reload Epoll EventSockfd_event =0; Stdin_event=0; Stdout_event=0; //Epoll cannot reload every time, so add an empty event to each FD if(Buffer_is_readable (&sendbuf)) {sockfd_event|=kwriteevent; } if(Buffer_is_writeable (&sendbuf)) {stdin_event|=kreadevent; } if(Buffer_is_readable (&recvbuf)) {stdout_event|=kwriteevent; } if(Buffer_is_writeable (&recvbuf)) {sockfd_event|=kreadevent; } epoll_mod_fd (EPOLLFD, SOCKFD, sockfd_event); EPOLL_MOD_FD (EPOLLFD, Stdin_fileno, stdin_event); EPOLL_MOD_FD (EPOLLFD, Stdout_fileno, stdout_event);
Understand this part of the code, the finishing part and poll basically consistent:
#define_gnu_source#include"sysutil.h"#include"Buffer.h"#include<sys/epoll.h>intMainintargcChar Const*argv[]) { //Create a client socket intSOCKFD = Tcp_client (0); //call the non-blocking connect function intret = Nonblocking_connect (SOCKFD,"localhost",9981, the); if(ret = =-1) {perror ("Connect Timeout."); Exit (Exit_failure); } //set three fd to Non-blockingActivate_nonblock (SOCKFD); Activate_nonblock (Stdin_fileno); Activate_nonblock (Stdout_fileno); buffer_t Recvbuf; //SOCKFD, stdout, Bufferbuffer_t SendBuf;//stdin, SOCKFD, Buffer//Initializing buffersBuffer_init (&recvbuf); Buffer_init (&sendbuf); //Create Epoll intEPOLLFD = Epoll_create1 (0); if(EPOLLFD = =-1) Err_exit ("Create Epoll"); structEpoll_event events[1024x768]; uint32_t sockfd_event=0; uint32_t stdin_event=0; uint32_t stdout_event=0; EPOLL_ADD_FD (EPOLLFD, SOCKFD, sockfd_event); EPOLL_ADD_FD (EPOLLFD, Stdin_fileno, stdin_event); EPOLL_ADD_FD (EPOLLFD, Stdout_fileno, stdout_event); while(1) { //Reload Epoll EventSockfd_event =0; Stdin_event=0; Stdout_event=0; //Epoll cannot reload every time, so add an empty event to each FD if(Buffer_is_readable (&sendbuf)) {sockfd_event|=kwriteevent; } if(Buffer_is_writeable (&sendbuf)) {stdin_event|=kreadevent; } if(Buffer_is_readable (&recvbuf)) {stdout_event|=kwriteevent; } if(Buffer_is_writeable (&recvbuf)) {sockfd_event|=kreadevent; } epoll_mod_fd (EPOLLFD, SOCKFD, sockfd_event); EPOLL_MOD_FD (EPOLLFD, Stdin_fileno, stdin_event); EPOLL_MOD_FD (EPOLLFD, Stdout_fileno, stdout_event); //listen for FD array intNready = epoll_wait (EPOLLFD, events,1024x768, the); if(Nready = =-1) Err_exit ("epoll Wait"); Else if(Nready = =0) {printf ("Epoll timeout.\n"); Continue; } Else { inti; for(i =0; i < Nready; ++i) {intPEERFD =EVENTS[I].DATA.FD; intRevents =events[i].events; if(PEERFD = = sockfd && revents &kreadrevent) { //receive data from SOCKFD to Recvbuf if(Buffer_read (&recvbuf, peerfd) = =0) {fprintf (stderr,"Server close.\n"); Exit (exit_success); } } if(PEERFD = = sockfd && revents &kwriterevent) {Buffer_write (&sendbuf, PEERFD);//writes data from SendBuf to SOCKFD } if(PEERFD = = Stdin_fileno && revents &kreadrevent) { //receive data from stdin write SendBuf if(Buffer_read (&sendbuf, peerfd) = =0) {fprintf (stderr,"exit.\n"); Exit (exit_success); } } if(PEERFD = = Stdout_fileno && revents &kwriterevent) {Buffer_write (&recvbuf, PEERFD);//output data from the RECVBUF to stdout } } } }}
Linux non-blocking IO (vii) Re-implementing the client using Epoll