- 1 Listen() ÇÔ¼ö ±¸Çö
- 2 ?OnEvent() ¿Í ?OnError()ÀÇ ±¸Çö
- 3 main()ÀÇ ±¸Çö
- 4 ¼Ò½ºÆÄÀÏ
- 5 ÀÌÈÄ °³¼±
1 Listen() ÇÔ¼ö ±¸Çö #
¼¹ö ±¸ÇöÀ» Çϱâ À§ÇØ ÇÊ¿¬ÀûÀ¸·Î listen ÄÝÀ» ÇؾßÇÏÁö¸¸, °ÅÀÇ ¸Å¹ø º¹»çÇؼ ³Ö´Ùº¸´Ï ±×°Íµµ ±ÍÂú¾Æ¼ µû·Î ºÐ¸®¸¦ ÇØ º¸¾Ò´Ù. ±×³É Listen(Æ÷Æ®¹øÈ£) ÄÝ ÇØÁÖ¸é µÇ°í ¼º°ø½Ã¿¡´Â fd ³Ñ¹ö, ½ÇÆнÿ¡´Â À½¼ö°ªÀÇ ¿¡·¯Äڵ带 ¸®ÅÏÇϵµ·Ï ÀÛ¼º.
int Listen(const unsigned nport)
{
struct sockaddr_in server_addr, client_addr;
int one=1, addrlen = sizeof(struct sockaddr_in);
int fd_listen;
if ((fd_listen = socket(PF_INET, SOCK_STREAM, 0)) < 0) return -1;
bzero((char *)&server_addr, sizeof(server_addr));
server_addr.sin_family = PF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(nport);
setsockopt(fd_listen, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one));
if((bind(fd_listen, (struct sockaddr *)&server_addr, sizeof(server_addr))) < 0 ){
close(fd_listen);
return -2;
}
if(listen(fd_listen, MAX_PENDING) < 0){
close(fd_listen);
return -3;
}
return fd_listen;
}
2 ?OnEvent() ¿Í ?OnError()ÀÇ ±¸Çö #
int OnError(const int fd, const int errcode)
{
return errcode;
}
int OnEvent(TEpollEvent &event)
{
int nread, nwrite;
char buf[1024];
if( event.events & EPOLLIN ){
// ³ªÁß¿¡ OnRead(); ·Î ¹Ù²Ü°ÍÀÌ´Ù.
nread = read(event.data.fd, buf, 1024);
if( nread < 1) return OnError(event.data.fd, nread);
else {
nwrite = write(event.data.fd, buf, nread);
buf[0] = 0;
}
}
if( event.events & EPOLLOUT){
// ³ªÁß¿¡ OnWrite(); ·Î ¹Ù²Ü°ÍÀÌ´Ù.
}
if( event.events & EPOLLERR) return OnError(event.data.fd, -1);
return 1;
}
Read À̺¥Æ®, Áï EPOLLIN ÀÌ ¹ß»ýÇßÀ»¶§¿¡ µ¥ÀÌÅ͸¦ ÀÐ°í ¹Ù·Î ¶Ç send(write) Çϵµ·Ï ÀÛ¼ºÇß´Ù. nwrite°¡ nread ¿Í °°ÀÌ ¾ÊÀ» °æ¿ì¿¡ ´ëÇÑ Ã³¸® (Áï, Àü¼Û°úÁ¤¿¡¼ÀÇ ¿¡·¯¹ß»ý)´Â ¿©±â¼´Â Á¦¿ÜÇÏ°í °£·«ÇÏ°Ô ÀÛ¼ºÇÏ¿´´Ù. ¿ª½Ã ³ªÁß¿¡
?SendBuffering ¹æ½ÄÀ¸·Î °íÃļ,
?OnWrite ¿¡¼ flush Çϵµ·Ï º¸¿ÏµÇ¾î¾ß WOULDBLOCK»óȲ¿¡ ´ëÇØ ´ëºñÇÒ ¼ö ÀÖ´Ù.
Read °úÁ¤¿¡¼ ¿¡·¯°¡ ¹ß»ýÇßÀ» °æ¿ì´Â
´ëºÎºÐ ¿¬°áÀÌ ²÷¾îÁ®¼ ¹ß»ýÇÑ´Ù. ÀÌ Äڵ忡¼´Â ¹Ù·Î
?OnError 󸮸¦ Çϵµ·Ï Çߴµ¥, ¸ÞÀÎÇÔ¼ö¿¡¼´Â
?OnEvent ¿¡¼ 1º¸´Ù ÀÛÀº°ª ( result < 1) ÀÎ °æ¿ì¿¡ epoll °ü½Éfd¿¡¼ »èÁ¦ÇÏ°í, ¿¬°áÀ» ´Ýµµ·Ï(close) ÀÛ¼ºÇÏ¿´´Ù.
3 main()ÀÇ ±¸Çö #
epoll °´Ã¼ ¼±¾ð
int main(void)
{
....
TEpoll epoll(MAX_CLIENT);
TEpollEvent events[MAX_EVENTS];
....
if(! epoll.is_epoll_init){
perror("epoll init error\n");
exit(-1);
}
....
?TEpollÀÇ ÀνºÅϽº epoll À» »ý¼ºÇÏ¿´´Ù. MAX_CLIENT´Â c10k°¡ °¡´ÉÇÏ´Ù´Â °Í ¶§¹®¿¡ À
Ϻη¯ 10,000 À¸·Î Á¤ÀÇÇÏ¿´´Ù ^^;
?TEpollEvent´Â ´Ü¼øÈ÷ epoll_eventÀÇ typedef ÀÌ´Ù. Çѹø¿¡ ó¸®ÇÒ À̺¥Æ® °¹¼ö¸¦ MAX_EVENTS·Î Á¤ÀÇÇÏ¿´´Âµ¥ ¿©±â¼´Â 200 À» Á¤ÇÏ¿´´Ù (ÀûÁ¤ÇÑ °ªÀÎÁö´Â Àß ¸ð¸£°Ú´Ù).
constructor¿¡¼, epoll ÃʱâÈ ¼º°ø¿©ºÎ¸¦ is_epoll_init º¯¼ö¿¡ ´ãÀ¸¹Ç·Î, °£´ÜÈ÷ °Ë»ç. ¹°·Ð epoll °¢ ÇÔ¼öµéµµ ¾ÈÀüÄÚµåµéÀ» ±¸ÇöÇϱâ´Â ÇßÁö¸¸
?TEpoll ÀÌ ¸¹ÀÌ Ãß»óȵǾîÀÖÁö ¾ÊÀ¸¹Ç·Î ¿ª½Ã³ª ¸¸Á·½º·´Áö ¾ÊÀº ÄÚµåÀÌ´Ù.
listen ÀÛ¾÷ ¹× epoll Ãß°¡
....
if((fd_listen = Listen(8000)) < 1){
perror("listen error\n");
exit(-1);
}
epoll.Add(fd_listen);
....
¾Õ¼ ÀÛ¼ºÇÑ Listen ÇÔ¼ö¸¦ ÄÝ. 8000 ¹ø Æ÷Æ®¸¦ listen Çϵµ·Ï ÇÏ°í, ¼º°ø½Ã¿¡ epoll ¿¡ ÀÌ fd ¸¦ µî·ÏÇÑ´Ù (Áï, ¿¬°á¿äûÀÌ µé¾î¿Ã°æ¿ì epoll ÀÌ °¨ÁöÇØ ³¾ °ÍÀÌ´Ù).
main loop ±¸Çö
for(;;){
n = epoll.Do(events, MAX_EVENTS, 10);
for(i=0; i<n; ++i){
if(events[i].data.fd == fd_listen){
fd_client = accept(fd_listen, (struct sockaddr *) &client_addr, (socklen_t *) &addrlen);
if(fd_client < 0){
perror("accept error\n");
continue;
}
// strcpy(cliaddr,inet_ntoa(client_addr.sin_addr));
SetNonBlocking(fd_client);
epoll.Add(fd_client);
} else {
if((result = OnEvent(events[i])) < 1){
printf("\n\nAn error is occured : %d", result);
close(events[i].data.fd);
epoll.Delete(events[i].data.fd);
}
}
}
}
return 0;
}
ÇÁ·Î±×·¥ÀÇ ¸ÞÀÎ ¹«ÇÑ ·çÇÁ. ¹Ýº¹Çؼ
?TEpoll.do ¸¦ ÄÝÇÑ´Ù. À̺¥Æ®°¡ ¹ß»ýÇÑ°æ¿ì ±× ¼ýÀÚ¸¸Å À̺¥Æ®¸¦ ó¸®Çϵµ·Ï ÇÑ´Ù. fdÀÇ ¼º°Ý¿¡ µû¶ó listen¼ÒÄÏ°ú ÀϹݼÒÄÏÀ» ±¸ºÐÇÏ¿´´Ù. »õ·Î¿î ¿¬°áÀÌ µé¾î¿Ã°æ¿ì ¼ÒÄÏÀ» nonblocking¸ðµå·Î º¯°æÇÏ°í¼ epollÀÇ °ü½Éfd·Î µî·ÏÇÏ¿´°í, ÀϹݼÒÄÏ¿¡¼´Â
?OnEvent·Î ±× 󸮸¦ ³Ñ°å´Ù. ¸¸¾à Á¾·á󸮰¡ ÇÊ¿äÇÑ °æ¿ì¸¦ À§ÇØ
?OnEventÀÇ °á°ú°ªÀ» ¹Þ¾Æ
?TEpoll.Delete ¸¦ È£ÃâÇϵµ·Ï Çß´Ù.
?TEpoll.Do ÀÇ ¼¼¹ø° ÆĶó¹ÌÅÍ´Â ´ë±â½Ã°£Àε¥, 10/1000ms·Î ÇÏ¿´´Ù. ÀÌ ¼ýÀÚ¸¦ 0 À¸·Î Çß´õ´Ï cpu »ç¿ë·üÀÌ 99.9%°¡ µÇ¾ú´Âµ¥ (½Ì±Û cpu), Àüü ÇÁ·Î¼¼½º ŸÀÓÀ¸·Î º¼¶§¿¡´Â À̺¥Æ®°¡ ¹ß»ýÇÏÁö ¾Ê°í ±×³É ´ë±âÇÏ´Â ½Ã°£ÀÌ °ÅÀÇ ÀüºÎÀ̹ǷÎ
?TEpoll.Do ¸¸ ¾öû³ª°Ô È£ÃâÇØ´ë°í ÀÖ°Ô µÉ °ÍÀÌ´Ù. ³²´Â ½Ã°£Àº ¿î¿µÃ¼Á¦¿¡ µ¹·ÁÁÖµµ·Ï 10 Á¤µµ·Î Àâ¾Ò´Ù. ÃÊ´ç 100¹ø
?TEpoll.Do¸¦ È£ÃâÇÏ°Ô µÇ´Âµ¥ ¹Ð·Áµé¾î¿À´Â µ¥ÀÌŸ°¡ ¸¹´Ù¸é ¹°·Ð 1000¹øµµ ³Ñ°Ô È£ÃâµÉ ¼öµµ ÀÖ´Ù. ¿©±â¼ 10ms¶ó´Â ¼ýÀÚ´Â À̺¥Æ®°¡ ¾øÀ»¶§ ÃÖ´ë À̸¸Å¸¸ ±â´Ù·Á¶ó¶ó´Â Àǹ̷ΠÇؼ®ÇÑ´Ù. ¹«Á¶°Ç 10ms ±â´Ù¸®¶ó´Â ¶æÀº ¾Æ´Ï´Ù.
4 ¼Ò½ºÆÄÀÏ #
5 ÀÌÈÄ °³¼± #
?TEpoll Ŭ·¡½º°¡ ¸¹Àº Ãß»óȸ¦ ÇÏ°í ÀÖÁö ¾ÊÀ¸¹Ç·Î, ¿©ÀüÈ÷ main ÇÁ·Î±×·¡¸Ó´Â epoll¿¡ ´ëÇØ ¼Ó¼ÓµéÀÌ ¾Ë°í ÀÖ¾î¾ß Çϸç ÀÌ°ÍÀº ¹Ù¶÷Á÷ÇÏÁö ¾Ê´Ù. ÇöÀçÀÇ
?TEpoll class¸¦ ±â¹ÝÀ¸·Î ÇÏ´Â
?TEpollSocketÀ» ¸¸µé°ÍÀÌ°í, ¿ÜºÎÀÎÅÍÆäÀ̽º´Â ÇÔ¼öÆ÷ÀÎÅ͸¦ ÀÌ¿ëÇÑ ÄݹéÀ¸·Î ±¸ÇöÇÒ °èȹ.
?TEpollSocketÀº listen, connect, accept¸¦ Æ÷ÇÔÇÏ°í À̺¥Æ®Æú¸µÀ» ÅëÇØ read, write, error À̺¥Æ®¸¦ °¨ÁöÇؼ »ç¿ëÀÚÀÇ ÇÔ¼ö¸¦ È£ÃâÇØÁÖµµ·Ï ÇÒ °ÍÀÌ´Ù.