The previous article introduces the Epoll's LT mode, the LT mode Note that the Epollout event needs to be canceled after all the data has been written successfully.
or change to Epollin.
And this time the Epoll et pattern, note that in the process of reading and writing in the loop to finish or read all the data,
Make sure you don't lose some data.
Because the Epoll et pattern is only triggered when two edge changes occur, the Read event is only changed from NULL in the kernel buffer to
Non-null notifies the user once, for write events, the kernel buffer notifies the user only once when the full becomes non-full.
Here is the code
int main ()
{
int eventsize = 20;
struct Epoll_event * epoll_eventslist = (struct epoll_event *) malloc (sizeof (struct epoll_event)
*eventsize);
Open an empty descriptor
int idlefd = open ("/dev/null", o_rdonly| O_CLOEXEC);
cout << "IDLEFD" <<IDLEFD <<endl;
Generate Listen Descriptor
int LISTENFD = socket (pf_inet, sock_cloexec | Sock_stream | Sock_nonblock, IPPROTO_TCP);
if (LISTENFD < 0)
{
Err_exit ("Socketfd");
}
Initialize address information
struct sockaddr_in servaddr;
memset (&servaddr,0, sizeof (struct sockaddr_in));
servaddr.sin_family = af_inet;
Servaddr.sin_port = htons (6667);
SERVADDR.SIN_ADDR.S_ADDR = htonl (Inaddr_any);
int on = 1;
if (setsockopt (LISTENFD, Sol_socket, so_reuseaddr, &on, sizeof (ON)) < 0)
Err_exit ("setsockopt");
if (Bind (LISTENFD, (struct sockaddr*) &servaddr, sizeof (SERVADDR)))
Err_exit ("Binderror");
if (Listen (LISTENFD, Somaxconn) < 0)
Err_exit ("Listen");
Record socket for client connection
Std::vector<int> clients;
Create EPOLLFD for managing the Epoll event table
int EPOLLFD;
EPOLLFD = Epoll_create1 (epoll_cloexec);
struct Epoll_event event;
EVENT.DATA.FD = LISTENFD;
Event.events = epollin| Epollet;
Add LISTENFD to the EPOLLFD management table
Epoll_ctl (EPOLLFD, Epoll_ctl_add, LISTENFD, &event);
The client address to receive the new connection
struct sockaddr_in peeraddr;
Socklen_t Peerlen;
int CONNFD;
For the sake of simplicity, write a large array, storing the content according to the file descriptor
In fact, many project code mining EPOLL.DATA.PTR callback specific read and write
Vector<string> Recievebuf;
for (int i = 0; i < 22222; i++)
{
Recievebuf.push_back ("");
}
while (1)
{
int nready = epoll_wait (EPOLLFD, Epoll_eventslist, Eventsize,-1);
if (Nready = =-1)
{
if (errno = = eintr)
Continue
Err_exit ("epoll_wait");
}
if (Nready = = 0)
Continue
Size not enough to re-open
if ((size_t) Nready = = eventsize)
{
if (eventsize * 2 >= 22222)
{
Err_exit ("Too many FDS");
}
struct Epoll_event * epoll_eventslist2 = (struct epoll_event *) malloc (sizeof (struct epoll_event) *
Eventsize);
if (EPOLL_EVENTSLIST2)
{
memcpy (epoll_eventslist2,epoll_eventslist,sizeof (struct epoll_event) * eventsize);
Eventsize = eventsize * 2;
Free (epoll_eventslist);
Epoll_eventslist = Epoll_eventslist2;
}
}
for (int i = 0; i < Nready; ++i)
{
Determines whether the events array state of wait returns is normal
if ((Epoll_eventslist[i].events & Epollerr) | |
(Epoll_eventslist[i].events & Epollhup))
{
fprintf (stderr, "Epoll error\n");
Close (EPOLL_EVENTSLIST[I].DATA.FD);
Continue
}
if (epoll_eventslist[i].data.fd = = LISTENFD)
{
Peerlen = sizeof (PEERADDR);
Et mode accept is placed in the while loop
Do
{
CONNFD =:: Accept4 (LISTENFD, (struct sockaddr*) &peeraddr,
&peerlen, Sock_nonblock | SOCK_CLOEXEC);
if (connfd <= 0)
Break
std::cout<< "ip=" <<inet_ntoa (PEERADDR.SIN_ADDR) <<
"Port=" <<ntohs (peeraddr.sin_port) <<std::endl;
Clients.push_back (CONNFD);
Add connd to the Epoll table to focus on reading events
EVENT.DATA.FD = CONNFD;
event.events = Epollin | Epollet;
Epoll_ctl (EPOLLFD, Epoll_ctl_add, CONNFD, &event);
cout << "Loop" <<endl;
cout << "Loop" << connfd << Endl;
}while (1);
Accept failed to determine whether to receive all the FD
cout << connfd << Endl;
if (CONNFD = =-1) {
if (errno! = Eagain && errno! = econnaborted
&& errno! = Eproto && errno! = eintr)
{
cout << "Error" <<endl;
Err_exit ("accept");
}
}
All requests are processed and completed
cout << "Continue" <<endl;
Continue
}//endif
else if (epoll_eventslist[i].events & Epollin)
{
CONNFD = EPOLL_EVENTSLIST[I].DATA.FD;
if (Connfd > 22222)
{
Close (CONNFD);
event = Epoll_eventslist[i];
Epoll_ctl (EPOLLFD, Epoll_ctl_del, CONNFD, &event);
Clients.erase (Std::remove (Clients.begin (), Clients.end (), CONNFD), Clients.end ());
Continue
}
Char buf[1024] = {0};
if (CONNFD < 0)
Continue
int ret = 0;
int total = 0;
Std::string strtemp;
while (1)
{
cout << "begin read" <<endl;
ret = Read (CONNFD, buf, 1024);
if (ret <= 0)
{
Break
}
strtemp + = string (BUF);
Total + = ret;
memset (buf, 0, 1024);
if (Ret < 1024)
{
Break
}
}//endwhile (1)
cout << "End read" <<endl;
RECIEVEBUF[CONNFD] = Strtemp.c_str ();
cout << "Buff data:" << recievebuf[connfd]<<endl;
if (ret = =-1)
{
if ((errno = = Eagain) | |
(errno = = Ewouldblock))
{
Because the kernel buffer is empty, the next time a data arrival is triggered Epollin
Continue
}
Err_exit ("read");
}//ENDIF ret = =-1
Connection Disconnect
if (ret = = 0)
{
std::cout<< "Client Close" <<std::endl;
Close (CONNFD);
event = Epoll_eventslist[i];
Epoll_ctl (EPOLLFD, Epoll_ctl_del, CONNFD, &event);
Clients.erase (Std::remove (Clients.begin (), Clients.end (), CONNFD), Clients.end ());
Continue
}
cout << "Turn to write" << Endl;
Change to write mode
EVENT.DATA.FD = CONNFD;
event.events = Epollout | Epollet;
Epoll_ctl (EPOLLFD, Epoll_ctl_mod, CONNFD, &event);
cout << "Epoll mod Change Success" << Endl;
}//end elif
else//write event
{
if (Epoll_eventslist[i].events & Epollout)
{
cout << "Begin write" <<endl;
CONNFD = EPOLL_EVENTSLIST[I].DATA.FD;
int count = 0;
int totalsend = 0;
Char buf[1024];
strcpy (buf, Recievebuf[connfd].c_str ());
cout << "Write Buff" <<buf<<endl;
while (1)
{
int totalcount = strlen (BUF);
int pos = 0;
Count = Write (EPOLL_EVENTSLIST[I].DATA.FD, buf + pos, totalcount);
cout << "Write Count:" << count;
if (Count < 0)
{
Break
}
if (Count < TotalCount)
{
TotalCount = Totalcount-count;
pos + = count;
}
Else
{
Break
}
}//end while
if (count = =-1)
{
if ((errno = = Eagain) | |
(errno = = Ewouldblock))
{
Because the kernel buffer is full
The kernel buffer is full.
Continue
}
Err_exit ("write");
}
if (count = = 0)
{
std::cout<< "Client Close" <<std::endl;
Close (CONNFD);
event = Epoll_eventslist[i];
Epoll_ctl (EPOLLFD, Epoll_ctl_del, CONNFD, &event);
Clients.erase (Std::remove (Clients.begin (), Clients.end (), CONNFD),
Clients.end ());
Continue
}
EVENT.DATA.FD = CONNFD;
Event.events = epollin| Epollet;
Epoll_ctl (EPOLLFD, Epoll_ctl_mod, CONNFD, &event);
}
}//end Eles Write Event
}
}
}
Source code: http://download.csdn.net/detail/secondtonone1/9486222
IO multiplexing Epoll (ii)