IO multiplexing Epoll (ii)

Source: Internet
Author: User
Tags epoll

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)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.