The biggest difference between 1.EPOLLLT and epollet is the notification mechanism of the event, see the difference between Epolllt and epollet in this article
2.EPOLLET mode does not mean that you want to iterate through all the data in the buffer and post a read code:
n = 0;
while ((nread = Read (FD, BUF + N, BUFSIZ-1)) > 0) {
n + = nread;
}
if (nread = = 1 && errno!= eagain) {
perror ("read error");
}
The pitfall of this code is that if the TCP buffer reads more than BUF, it will cause a stack overflow, so it is not correct to iterate through the buffer data until you encounter Eagain.
3. It is necessary to note that the first increase and every time the events of the socket, you need to specify Epollet, not add once will be permanent Epollet mode
struct epoll_event ev;
ev.events = Epollin | Epollet; /* et mode *
/ev.data.fd = SOCKFD;
if ( -1 = = Epoll_ctl (EFD, Epoll_ctl_add, SOCKFD, &ev)) {
perror ("Epoll_ctl epoll_ctl_add fail");
}
The difference between 4.EPOLLLT and Epollet when reading data is that when the data is not read, Epollet must register the readable event
5.EPOLLLT and Epollet behavior is consistent when sending data, all require the application layer to actively determine whether there is data to be sent
Correct read and write mode in 6.EPOLLLT mode
The understanding of the epoll_event structural body
Man 2 epoll_ctl
typedef Union EPOLL_DATA {
void *ptr;
int FD;
__uint32_t u32;
__uint64_t u64;
} epoll_data_t;
struct Epoll_event {
__uint32_t events; /* Epoll Events * *
epoll_data_t data; /* User Data variable *
/};
Test code:
-----server.cpp-----
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <sys/epoll.h> #include < fcntl.h> #include <errno.h> #include <string.h> #define MAX_EVENTS 1000 #define MAX_LEN 1024/* Reference Man EP Oll_ctl Epollin readable epollout writable EPOLLPRI emergency Data epollrdhup error EPOLLERR error epollhup error *//set non-blocking static void setnonblocking (int sockfd)
{int flag = FCNTL (SOCKFD, F_GETFL, 0);
if (Flag < 0) {perror ("Fcntl F_GETFL fail");
Return if (Fcntl (SOCKFD, F_SETFL, flag |
O_nonblock) < 0) {perror ("Fcntl F_SETFL fail");
}//Add epoll event static int epoll_add (int efd, int sockfd) {struct epoll_event ev; ev.events = Epollin | Epollet;
/* et mode */ev.data.fd = SOCKFD;
if ( -1 = = Epoll_ctl (EFD, Epoll_ctl_add, SOCKFD, &ev)) {perror ("Epoll_ctl epoll_ctl_add fail"); return 1;
return 0;
}//Modify Epoll event, ET static void Epoll_write (int efd, int sockfd, bool enable) {struct epoll_event ev; ev.events = Epollin | Epollet | (Enable?)
epollout:0);
EV.DATA.FD = SOCKFD;
Epoll_ctl (EFD, Epoll_ctl_mod, SOCKFD, &ev);
}//delete epoll event static void Epoll_del (int efd, int sockfd) {perror ("close by");
Epoll_ctl (EFD, Epoll_ctl_del, SOCKFD, NULL);
Close (SOCKFD);
//read, fixed-length int readn (int fd, void *vptr, size_t n) {//Look man 2 read size_t nleft;
int nread;
Char *ptr;
ptr = (char*) vptr;
Nleft = n;
while (Nleft > 0) {nread = (int) read (FD, PTR, nleft);
if (Nread < 0) {if (errno = = eintr) nread = 0;/* call Read () again/else return-1; /* maybe errno = = Eagain/Else if (0 = nread) {break; * EOF/} nleft-= Nread
;
PTR + = nread; return (N-nleft); /* Return >= 0///write, fixed-length int writen (int fd, const void *vptr, size_t n) {//Read man 2 write size_t nleft;
int Nwritten;
const char *ptr;
ptr = (char*) vptr;
Nleft = n;
while (Nleft > 0) {nwritten = write (FD, PTR, nleft); if (nwritten <= 0) {if (Nwritten < 0 && errno = = eintr) Nwritten = 0;/* Call W Rite () again */Else return (-1);
/* ERROR/} Nleft-= Nwritten;
PTR + = Nwritten;
return (n);
//Whether there is data to send bool Ifsend () {return true;}
int main () {//socket int LISTENFD;
struct sockaddr_in servaddr;
Short port = 9527;
servaddr.sin_family = af_inet;
SERVADDR.SIN_ADDR.S_ADDR = htonl (Inaddr_any);
Servaddr.sin_port = htons (port);
LISTENFD = socket (af_inet, sock_stream, 0); Setnonblocking (LISTENFD);
Non-blocking int res = bind (LISTENFD, (SOCKADDR *) &servaddr, sizeof (SERVADDR)) when accept calls; if (0 == res) printf ("Server bind success, 0.0.0.0:%d\n", port);
else {perror ("bind fail");
Exit (Exit_failure);
res = Listen (LISTENFD, 100);
if (0 = res) printf ("Server Listen success\n");
else {perror ("listen Fail");
Exit (Exit_failure);
}//Epoll create,see man epoll_create struct epoll_event ev, events[max_events];
int EPOLLFD = epoll_create (10);
if ( -1 = EPOLLFD) {perror ("epoll_create fail");
Exit (Exit_failure);
}//Epoll Add if (Epoll_add (EPOLLFD, LISTENFD)) {exit (exit_failure); for (;;)
{int Nfds = epoll_wait (EPOLLFD, events, max_events,-1);
if ( -1 = Nfds) {perror ("epoll_wait fail");
Exit (Exit_failure); for (int n = 0; n < Nfds ++n) {if (events[n].data.fd = = listenfd) {struct sock
Addr_in cliaddr;
socklen_t len = sizeof (CLIADDR); int CONNFD = Accept (LISTENFD, (SOCKADDR *) &cliaddr, &len);
if ( -1 = connfd) {perror ("accept fail");
Continue
} setnonblocking (CONNFD);
if (Epoll_add (EPOLLFD, CONNFD)) {close (CONNFD);
Continue
}//Here are some processing, such as parsing cliaddr char Buff[inet_addrstrlen + 1] = {0};
Inet_ntop (af_inet, &cliaddr.sin_addr, Buff, inet_addrstrlen);
uint16_t port = ntohs (Cliaddr.sin_port);
printf ("Connection from%s, Port%d\n", buff, port);
else if (events[n].events & Epollin) {char Buffer[max_len + 1] = {0};/* Keep the end ' * '
size_t count = Max_len;
int connfd = EVENTS[N].DATA.FD;
int res = READN (connfd, buffer, count);
Handling Network anomalies if (Res < 0 && errno!= eagain) {Epoll_del (EPOLLFD, CONNFD);
Continue
else if (0 = res) {Epoll_del (EPOLLFD, CONNFD);
Continue */* (res = = 1 && errno = = eagain) data read/if (res > 0 && ifsend ())
/* Data not read, there are data sent/Epoll_write (EPOLLFD, CONNFD, true);
else if (res > 0)/* Data not read, no data sent/Epoll_write (EPOLLFD, CONNFD, false);
else if (ifsend ())/* Data read, there are data sent/Epoll_write (EPOLLFD, CONNFD, true);
if (strlen (buffer)!= 0) {printf ("fd:%d, read len:%ld\n", CONNFD, strlen (buffer)); } else if (Events[n].events & epollout) {const char* vptr = "Hi client!"; * Spoofed send data
* * int connfd = EVENTS[N].DATA.FD; size_t count = strlen (vptr);
int len = writen (CONNFD, vptr, Count);
Handling network Anomalies if (Len < 0 && errno!= eagain) {Epoll_del (EPOLLFD, CONNFD);
Continue
if (Len > 0) {printf ("fd:%d, Write len:%d\n", CONNFD, Len);
} if (Len < count) {Epoll_write (EPOLLFD, CONNFD, true);///writable data, registration Epollout * *
else {epoll_write (EPOLLFD, CONNFD, false);//No writable data, registration Epollin * * } else if (Events[n].events & Epollpri) {//pass} else if (Events[n].even
TS & epollrdhup) {Epoll_del (EPOLLFD, EVENTS[N].DATA.FD);
else if (events[n].events & Epollerr) {Epoll_del (EPOLLFD, EVENTS[N].DATA.FD); else if (Events[n].events & EpollhuP) {Epoll_del (EPOLLFD, EVENTS[N].DATA.FD); } else {//Pass}}}}
-----client.cpp-----
#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> # Include <arpa/inet.h> #include <stdlib.h> #include <unistd.h> #include <sys/epoll.h> #include & lt;fcntl.h> #include <errno.h> #include <string.h>//setting non-blocking static void setnonblocking (int sockfd) {i
NT flag = Fcntl (SOCKFD, F_GETFL, 0);
if (Flag < 0) {perror ("Fcntl F_GETFL fail");
Return if (Fcntl (SOCKFD, F_SETFL, flag |
O_nonblock) < 0) {perror ("Fcntl F_SETFL fail");
//read, fixed-length int readn (int fd, void *vptr, size_t n) {/* look man 2 read/* size_t Nleft;
int nread;
Char *ptr;
ptr = (char*) vptr;
Nleft = n;
while (Nleft > 0) {nread = (int) read (FD, PTR, nleft);
if (Nread < 0) {if (errno = = eintr) nread = 0;/* call Read () again/else return-1;
/* maybe errno = = Eagain * else if (0 = nread) {break;/* EOF/} Nleft-= Nread;
PTR + = nread; return (N-nleft); /* return >= 0/}//write, fixed-length int writen (int fd, const void *vptr, size_t n) {/* Look man 2 write/size_t Nlef
T
int Nwritten;
const char *ptr;
ptr = (char*) vptr;
Nleft = n;
while (Nleft > 0) {nwritten = write (FD, PTR, nleft); if (nwritten <= 0) {if (Nwritten < 0 && errno = = eintr) Nwritten = 0;/* Call W Rite () again */Else return (-1);
/* ERROR/} Nleft-= Nwritten;
PTR + = Nwritten;
return (n);
int main () {//socket struct sockaddr_in servaddr;
Short port = 9527;
int SOCKFD = socket (af_inet, sock_stream, 0);
servaddr.sin_family = af_inet;
SERVADDR.SIN_ADDR.S_ADDR = inet_addr ("127.0.0.1");
Servaddr.sin_port = htons (port); Setnonblocking (SoCKFD);
if (Connect (SOCKFD, (SOCKADDR *) &servaddr, sizeof (sockaddr_in)) < 0) {if (errno!= einprogress) {
Perror ("Connect Fail");
Close (SOCKFD);
Exit (Exit_failure);
} const char* sendbuf = "Hello server!"; for (;;)
{//write int len = writen (SOCKFD, SendBuf, strlen (SENDBUF));
if (Len < 0 && errno!= eagain) {break;
if (Len > 0) {printf ("fd:%d, Write len:%d\n", SOCKFD, Len);
}//Read char recvbuf[1024+1] = {0};
int res = READN (SOCKFD, RECVBUF, 1024);
if (Res < 0 && errno!= eagain) {break;
else if (0 = res) {break;
} if (strlen (RECVBUF) > 0) {printf ("fd:%d, read len:%ld\n", SOCKFD, strlen (RECVBUF));
Sleep (1);
} perror ("Close by");
Close (SOCKFD); }