
ããããã¹ãŠå§ãŸã£ãæ¹æ³
çŸåšã®ç§ã®ä»äºã¯ãã¹ã¯ãããã¢ããªã±ãŒã·ã§ã³ã«é¢é£ããŠãããšããäºå®ã«ãããããããç§ã¯æè¿ããµãŒããŒãã¯ãããžãŒãã«èå³ãæã£ãŠããŸãã ã€ã³ã¿ãŒãããããµãŒãã£ã³ããããman'ovãèªãã ããèªåçšã«ãµãŒããŒã®ãããªãã®ãæžã蟌ãããšããããã人ãããŸããæ確ãªç®æšããªãããããããæè¿è¡ããããã¹ãŠã§ãã ãããããã¿ã¹ã¯ãæãã€ããããããªãã®ã¹ãã«ã¬ãã«ãããã»ã©æªãã¯ããªãã§ãã ããã
ä»äºããéå±ã«ãªã£ãããæç¹ã§ãããç¥ãããŠããæ±äººæ€çŽ¢ãªãœãŒã¹ã®1ã€ããã§ãã¯ããŸãããåžå ŽãèŠãã®ã¯æ°ã«ããªãããšã§ããçªç¶ãèå³æ·±ãããšãæµ®ãã³äžãããŸãã ãããããããªãã«èå³ãããã§ããããã ãã®ãããªææ¡ã®äžã§ããã¹ãã¿ã¹ã¯ã䌎ãææ¡ãæ¥ãŸããã ãã¹ãã¿ã¹ã¯ã¯ãHTTPãããã³ã«ã®å®è£
ã䜿çšããŠãLinuxã§C ++ã§WebServerãäœæããããšã§ãã æ°åããªã...
ãã¹ãã¿ã¹ã¯ã®ãã¬ãŒãºãGoogleã«å°å
¥ãããšããã
RSDNãã©ãŒã©ã ã§æçã®ãã¹ãã¿ã¹ã¯ã§ã¯ãªããããã«é¢ããã¬ãã¥ãŒãèŠã€ããŸããã ã¿ã¹ã¯ã¯ãç§ã®ã¡ãŒã©ãŒã«ãã1察1ã§ããã å²ãåœãŠãšããŠã圌ã¯ããŸããã§ããã ååã¯åçŽã§ãããã¹ãã¿ã¹ã¯ã«äŸ¡å€ãããå Žåã¯ã4æé以å
ã®äœæ¥æéã§èšèšããå¿
èŠããããŸãã ããããèªã¿èãããããå Žæã§è©Šããããã¹ãŠãè©Šãããšã¯èå³æ·±ãããšã§ããã ãããã€ã³ã»ã³ãã£ãã«ãªããŸããã èå³æ·±ãåé¡ã®å£°æã æ¡çšæ
åœè
ããã®ãã®ã§ããããããã®ã¿ã¹ã¯ãã©ã®ãªãã£ã¹ã«å±ããŠãããã¯èšããŸããããããã»ã©éèŠã§ããããŸããã
ãã®èšäºã§ã¯ããã®ãããã¯ã§èŠã€ããã¢ãããŒããšé¢é£APIã調ã¹ãŸãã ããŸããŸãªã¢ãããŒããšããŒã«ã䜿çšããŠWebServerã®ããã€ãã®å®è£
ãæäŸããåãåã£ããã¯ã©ãããã®æ¯èŒãã¹ããå®æœããŸããã ãã®èšäºã¯ãã²ããçãããããµãŒããŒã©ã€ã¿ãŒã察象ãšã¯ããŠããŸããããã¬ãã¥ãŒãšããŠïŒãã¹ãã ãã§ãªãïŒåæ§ã®ã¿ã¹ã¯ã«ééãã人ã圹ã«ç«ã€ãããããŸããã èšäºãæžãããšã¯çµéšãå
±æããããšã ãã§ãªãããããèªåã§è£å
ããããšã«ãªããããããªãã®ã§ãç§ã¯ã¿ããªãç¹ã«ãã²ããçãããããµãŒããŒã©ã€ã¿ãŒãã建èšçãªã³ã¡ã³ããããããæããŸã...
APIãšã©ã€ãã©ãªã®æŠèŠ
ãµãŒããŒåŽã®ã¹ã¯ãªããããŒã«ãæ€èšããçµæãAPI * nix of systemsãWindows APIïŒãã®ãã©ãããã©ãŒã ã¯ãã®ã¿ã¹ã¯ã®ç®çã§ã¯ãããŸãããã衚瀺ãããŸããïŒãããã³boost.asioãlibeventãªã©ã®ã©ã€ãã©ãªããããŸããã
Berkeleyãœã±ãã㯠ãæ®éçã§ããŒã¿ãã«ãªã¡ã«ããºã ã§ãããå®å
šã«æ確ã«ç§»æ€ãããŠããããã§ã¯ãããŸããã ãã®ãããäžéšã®ãã©ãããã©ãŒã ã§ã¯ãœã±ãããéããããã«è¿ããäžéšã®ã¯ããŒãºãœã±ããã§ã¯ã ã©ã€ãã©ãªãåæåããå¿
èŠããããã®ïŒWindows-WSAStartup / WSACleanupïŒãããã§ãªããã®ããããŸãã ã©ããã§ã¯ããœã±ããèšè¿°åã¯intåã§ãã©ããã§ã¯SOCKETãšãã®ä»ã®å°ããªéãã§ãã pImplãªã©ã®ãã¹ãŠã®çš®é¡ã®ã¯ãã¹ãã©ãããã©ãŒã ããã°ã©ãã³ã°ã¢ãããŒããé©çšããªãå Žåãåãã³ãŒãã¯æ©èœãããå€ãã®å Žåãç°ãªããã©ãããã©ãŒã ã§åãæ¹æ³ã§ãã«ããããŸãã ãããã®å°ããªãã®ã¯ãã¹ãŠã
boost.asio ã
libeventãªã©ã®ã©ã€ãã©ãªã«é ãããŠããŸãã ããã«ããã®ãããªã©ã€ãã©ãªã¯ã察å¿ãããã©ãããã©ãŒã ã®ããå
·äœçãªAPIã¡ãœããã䜿çšããŠããœã±ããã䜿çšããæé©ãªäœæ¥ãå®è£
ãããã©ãããã©ãŒã ã®ãã³ããªãã«äŸ¿å©ãªã€ã³ã¿ãŒãã§ã€ã¹ããŠãŒã¶ãŒã«æäŸããŸãã
ãµãŒããŒã®äœæ¥ãéåžžã«äžè¬åããæ¹æ³ã§å®è¡ãããšã次ã®äžé£ã®ã¢ã¯ã·ã§ã³ãçºçããŸãã
- ãœã±ãããäœæãã
- ãœã±ããããããã¯ãŒã¯ã€ã³ã¿ãŒãã§ã€ã¹ã«ãã€ã³ããã
- ç¹å®ã®ãããã¯ãŒã¯ã€ã³ã¿ãŒãã§ã€ã¹ã«ãã€ã³ãããããœã±ããããªãã¹ã³ãã
- çä¿¡æ¥ç¶ãåãå
¥ãã
- ãœã±ããã®ã€ãã³ãã«å¿çãã
5çªç®ãé€ããã¹ãŠã®ãã€ã³ãã¯æ¯èŒçé¡äŒŒããŠãããã»ãšãã©é¢å¿ããããŸãããããœã±ããã§çºçããã€ãã³ãã«å¿çããããã®å€ãã®ã¡ã«ããºã ãããããããã®ã»ãšãã©ã¯åãã©ãããã©ãŒã ã«åºæã§ãã
WindowsãèŠããšã次ã®æ¹æ³ãããããŸãã
- éžæã䜿çšããŸãã åºæ¬çã«ãä»ã®ãã©ãããã©ãŒã ã®ã³ãŒããšã®äºææ§ã®ããã«ãããã§ã¯ãã以äžã®å©ç¹ã¯ãããŸããã
- WSAAsyncSelect-ãŠã£ã³ããŠåãããã¢ããªã±ãŒã·ã§ã³ããœã±ããäžã®ã€ãã³ãããŠã£ã³ããŠåããããã¥ãŒã«éä¿¡ããããã«èšèšãããŠããŸãã éãã¯ãªãããµãŒããŒã³ãŒãã¡ã«ããºã ãšããŠã¯èå³æ·±ããã®ã§ã¯ãããŸããã
- WSAEventSelectã¯ããããã¯ãŒã¯ã€ã³ã¿ãŒãã§ã€ã¹äžã®ã€ãã³ããªããžã§ã¯ããåŠçããŸãã ãã§ã«ããé
åçãªããŒã«ã ã€ãŸã åæã«ãµãŒãã¹ãæäŸããæ¥ç¶ãæ°çŸãè¶
ããªãããã«ãµãŒããŒãèšç»ããå Žåãããã¯ããã©ãŒãã³ã¹/éçºé床ã®åºæºã«ãããšæé©ãªã¡ã«ããºã ã§ãã
- I / Oã®éè€ã¯WSAEventSelectãããé«éãªã¡ã«ããºã ã§ãããéçºããã®ãé¢åã§ãã
- I / Oå®äºããŒã-é«è² è·ãµãŒããŒã¢ããªã±ãŒã·ã§ã³çšã
Windowsçšã®ãããã¯ãŒã¯ãœãããŠã§ã¢ã®éçºã«é¢ããåªããæžç±ããããŸã-ãMicrosoft Windowsãããã¯ãŒã¯ã§ã®ããã°ã©ãã³ã°ãã
* nixã·ã¹ãã ãèŠããšãã€ãã³ãã»ã¬ã¯ã¿ãŒã®å°ããªã»ããããããŸãã
- åãéžæã ãããŠåã³ã圌ã®åœ¹å²ã¯ä»ã®ãã©ãããã©ãŒã ãšã®äºææ§ã§ãã ãŸããç£èŠããŠãããœã±ããã®ããããã§ã€ãã³ããçºçãããšããªã¬ãŒãããïŒå¶åŸ¡ãè¿ãïŒãããé«éã§ã¯ãããŸããã ãã®ãããªæäœã®åŸããã¹ãŠãå®è¡ããŠãã€ãã³ããçºçãããœã±ããã確èªããå¿
èŠããããŸãã èŠçŽïŒ1ã€ã®æäœã¯ã芳枬ããããœã±ããã®ããŒã«å
šäœã§å®è¡ãããŸãã
- pollã¯ããé«éãªã¡ã«ããºã ã§ãããç£èŠçšã®å€æ°ã®ãœã±ããçšã«èšèšãããŠããŸããã
- epollïŒLinuxã·ã¹ãã ïŒãškqueueïŒFreeBSDïŒã¯ã»ãŒåãã¡ã«ããºã ã§ãããäžéšã®ãã©ãŒã©ã ã®ççãªFreeBSDãã¡ã³ã¯kqueueã®æ¹ãã¯ããã«åŒ·åã ãšåŒ·ã䞻匵ããŠããŸãã ç§ãã¡ã¯èæŠãå©é·ããŸãã...ãããã®ã¡ã«ããºã ã¯ã* nixã·ã¹ãã ã§è² è·ã®é«ããµãŒããŒã¢ããªã±ãŒã·ã§ã³ãäœæããéã®äž»ãªãã®ãšèããããšãã§ããŸãã åäœåçãšãã®å°å³ãç°¡åã«èª¬æãããšãäœããçºçãããœã±ããã®ã¿ã«é¢é£ããäžå®éã®æ
å ±ãè¿ããããã¹ãŠãå®è¡ããŠäœãã©ãã§çºçãããã確èªããå¿
èŠã¯ãããŸããã ãŸãããããã®ã¡ã«ããºã ã¯ãåæã«ãµãŒãã¹ãããå€æ°ã®æ¥ç¶çšã«èšèšãããŠããŸãã
èšè¿°åã®ã€ãã³ããåŸ
æ©ããæ©èœã«å ããŠãããã«å°ãããéåžžã«äŸ¿å©ãªãã®ãããã€ããããŸãã
- sendfileïŒLinuxïŒããã³TransmitFileïŒWindowsïŒã䜿çšãããšããéä¿¡å
ãããã³ãéä¿¡å
ãã®ããã€ãã®èšè¿°åããã£ãŒãããŠããŒã¿ãéä¿¡ã§ããŸãã HTTPãµãŒããŒã§ã¯ããã¡ã€ã«ã転éããå¿
èŠãããå Žåã«éåžžã«äŸ¿å©ã§ããããã¯ãããã©ãŒãã³ã¹ã«ãã©ã¹ã®åœ±é¿ãäžããããããã¡ãŒã®å²ãåœãŠãšèªã¿åã/æžã蟌ã¿é¢æ°ã®åŒã³åºããäžèŠã«ãªãããã§ãã
- aio-ç¹å®ã®éã®äœæ¥ããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã«è»¢éã§ããŸããããã«ããããã¡ã€ã«èšè¿°åã§éåææäœãå®è¡ã§ããããã«ãªããŸãã ããšãã°ãã·ã¹ãã ã«ãããã¡ãŒãäŒããã·ã°ãã«ãã©ã®ããã«çµäºãããããã®ãã¡ã€ã«èšè¿°åã«æžã蟌ã¿ãŸãïŒèªã¿åããšåæ§ïŒã
- Neiglã¢ã«ãŽãªãºã ã¯ããããã¡ãªã³ã°ã®é
延ãªãã«ãããã¯ãŒã¯ã«ããŒã¿ãå°ããã€éä¿¡ããå¿
èŠãããã¢ããªã±ãŒã·ã§ã³ãäœæãããšãã«åœ¹ç«ã¡ãŸãããåžžã«åœ¹ç«ã€ãšã¯éããŸããã HTTPãµãŒããŒãªã©ã®ã¢ããªã±ãŒã·ã§ã³ã§ã¯ãã·ã¹ãã ã«éä¿¡ããŒã¿ããããã¡ãŒããå¯èœãªéãæçšãªæ
å ±ãšãšãã«TCPãã¬ãŒã ã«éä¿¡ããããã«æ瀺ããããšããå§ãããŸãïŒããã«ã¯ãTCP_CORKãªã©ã®ãœã±ãããªãã·ã§ã³ã䜿çšã§ããŸãïŒã
- ãããŠãã¡ããããã³ããããã³ã°ãœã±ããã ã³ã¡ã³ããªã...
- ãŸããwritevïŒnixïŒãªã©ã®é¢æ°ïŒããã³Windowsã®åæ§ã®WSAé¢æ°ïŒã䜿çšãããšãè€æ°ã®ãããã¡ãŒãäžåºŠã«éä¿¡ã§ããŸããããã¯ãHTTPãã±ããããããŒãšããã«æ·»ä»ãããããŒã¿ãéä¿¡ããåæã«ã·ã¹ãã ã³ãŒã«ã®æ°ãç¯çŽããå¿
èŠãããå Žåã«äŸ¿å©ã§ãã
ã©ã€ãã©ãªãŒãã¹ã¿ãŒã¿ãŒçšã®ã³ãŒããšãšãã«äœ¿çšããããšããå§ãããŸããããã«ã€ããŠã¯ãäŸãšããŠboost.asioãšlibeventã䜿çšããŠè¡ããŸãã boost.asioã¯ãããã¯ãŒã¯ã¢ããªã±ãŒã·ã§ã³ã®éçºã倧å¹
ã«ç°¡çŽ åããŸããlibeventã¯ãµãŒããŒã¯ã©ã·ãã¯ã§ãã
Epollã®å®è£
epollãpollãselectã®ãããã¯ãŒã¯ã€ãã³ãã«å¿çããããã«ã©ã®ãããªã¡ã«ããºã ãéžæãããšããŠããä»ã«ãå€ãã®ãã¥ã¢ã³ã¹ããããŸãã
ãã«ãã¹ã¬ãããµãŒããŒãå®è£
ããéã®æåã®è³ªåã®1ã€ã¯ãã¹ã¬ããæ°ã®éžæã§ãã ãã€ãŠãã¬ãŒãã³ã°ãç䌌æŠéã®ç®çã§ããœã±ãããµãŒããŒãããã°ããçµã¿ç«ãŠãå¿
èŠããã£ã人ã®ã»ãšãã©ã¯ãã1ã€ã®æ¥ç¶-1ã€ã®ã¹ã¬ããããšããæŠç¥ãéžæããŸããã ãã®ã¢ãããŒãã«ã¯é·æãšçæããããŸãã æ倧ã®ãã©ã¹ã¯ãéçºã®å®¹æãã§ãã å€ãã®æ¬ ç¹ããããŸãïŒå€§éã®ã·ã¹ãã ãªãœãŒã¹ãå€ãã®åæã¢ã¯ã·ã§ã³ïŒã³ãŒããäœããšåæããäœãïŒã ãã ããã»ãã·ã§ã³éã«ç¹å¥ãªå
±ééšåããªãããããã®ã¢ãããŒãã¯åæã®ç¹ã§HTTPãµãŒããŒã«ãšã£ãŠæªãããšã§ã¯ãããŸããã ããããéçºã®åçŽãã«ãããããããç§ã¯ãã®å®è£
ã®ããã«ãã®æŠç¥ãèæ
®ããŸããã§ããã ã¹ã¬ããæ°ã®æé©ãªéžæã«ã¯ããŸããŸãªæšå¥šäºé
ããããŸããããã¯ãã·ã¹ãã å
ã®ããã»ããµ/ããã»ããµã³ã¢ã®æ°ã§ãåãæ°ã§ãããç¹å®ã®ä¿æ°ããããŸãã ææ¡ãããå®è£
ã§ã¯ãã¯ãŒã«ãŒã¹ã¬ããã®æ°ã¯ããµãŒããŒã®èµ·åæã«ãŠãŒã¶ãŒã«ãã£ãŠèšå®ããããªãã·ã§ã³ã®ãã©ã¡ãŒã¿ãŒã§ãã ç§ã«ãšã£ãŠã¯ãã¯ãŒã¯ãããŒã®æ°ã¯ããã»ããµ/ã³ã¢ã®æ°ã«2ãæãããã®ã«çãããšå€æãããŸããã
çŸåšã®ã³ã³ããã¹ãã§ã¯ãã¯ãŒã¯ãããŒã¯ãŠãŒã¶ãŒèŠæ±ãåŠçããã¹ã¬ãããšããŠç解ãããå¿
èŠããããŸãã ãããã®ãããŒã«å ããŠããªã¹ãã³ã°ã¹ããªãŒã ãšã¡ã€ã³ã¹ããªãŒã ã®2ã€ãå«ãŸããŠããŸããã ãªã¹ãã³ã°ã¹ããªãŒã -ãµãŒããŒãœã±ããããªãã¹ã³ããçä¿¡æ¥ç¶ãåãå
¥ããåŠçã®ããã®ã¯ãŒã¯ãããŒã®ãã¥ãŒã«å
¥ããããŸãã ã¡ã€ã³ã¹ã¬ãã-ãµãŒããŒãèµ·åãããŠãŒã¶ãŒããã®ç¹å®ã®ã¢ã¯ã·ã§ã³ãåŸ
ã£ãŠåæ¢ããŸãã
ãã®äŸãå®è£
ãããšãã«èå³ãæã£ã2çªç®ã®è³ªåã¯ãepollã䜿çšããéã®ãããŒãšãããã¯ãŒã¯ã€ãã³ãã®åŠçæ¹æ³ã§ãã ç§ãæåã«æãã€ããã®ã¯ã1ã€ã®ã¹ã¬ããã§epollã«ãã£ãŠç£èŠãããŠãããã¹ãŠã®ã€ãã³ãã«åå¿ããããããä»ã®ã¹ã¬ããïŒã¯ãŒã«ãŒïŒã§åŠçããç¹å®ã®ãã¥ãŒã«æž¡ãããšã§ããã ã€ãŸã 1ã€ã®ã¹ã¬ããã¯ããªã¹ãã³ã°ãœã±ããäžã®çä¿¡ã€ãã³ããšãåä¿¡ããæ¥ç¶ãžã®ããŒã¿ã®å°çã«é¢ããã€ãã³ããšãéããããŠããæ¥ç¶ã«é¢ããã€ãã³ãã®äž¡æ¹ãç£èŠããŸãã ã€ãã³ããååŸãããã¥ãŒã«å
¥ããã¯ãŒã«ãŒã¹ã¬ããã«éç¥ããæ°ããæ¥ç¶ãåãå
¥ããããã«acceptãšåŒã°ããã¯ãŒã«ãŒã¹ã¬ãããè¿œå ããepollãèªã¿åããæžã蟌ã¿ãè¿œå ããæ¥ç¶ã®ç£èŠãœã±ããã®ããŒã«ãéããŸãã ãœã±ããããã®ããŒã¿ã®èªã¿åããªã©ã1ã€ã®ã€ãã³ãã®åŠçäžã«ããœã±ãããéããããšã«é¢ããã€ãã³ãããã®ãœã±ããã®ãã¥ãŒã«æ¢ã«ããå¯èœæ§ãããããã決å®ã¯ééã£ãŠããŸãã ãã¡ãããèªã¿åãã¯ãšã©ãŒã§å€±æããŸãããæ¥ç¶ã«é¢é£ãããã¹ãŠã®ãªãœãŒã¹ãã¯ãªã¢ããæé ã«ã¯ãªããŸãããããã¥ãŒãããã®ã€ãã³ããæžç®ããå Žåã®ã¿ã§ãã ç§ã®å®è£
ã§ã¯ãå€ãã®ãœã±ããã¯ããŒãžã£ã€ãã³ãã倱ãããŸããã å®è£
ã¯ããè€éã«ãªããåæã®å Žæã®æ°ãå¢ããå¥åŠãªç¶æ³ã§ã¯ãããããçºçããŸããã æ»ã¯å¥ã®çç±ã§ããã epollã€ãã³ãã®æ§é å
ã®åãœã±ããã§ã¯ããŠãŒã¶ãŒããŒã¿ãšããŠããã€ã³ã¿ãŒãã»ãã·ã§ã³ãªããžã§ã¯ãã«ã¢ã¿ãããããã¯ã©ã€ã¢ã³ããªããžã§ã¯ããéãããããŸã§ãã¯ã©ã€ã¢ã³ããšã®ãã¹ãŠã®äœæ¥ãè¡ããŸããã ã€ãã³ãåŠçã®ã·ãŒã±ã³ã¹ãããè€éã«ãªã£ãããããŠãŒã¶ãŒããŒã¿ãšããŠé¢é£ä»ãããããªããžã§ã¯ããæ¢ã«åé€ãããããïŒããšãã°ãã»ãã·ã§ã³ãå€éšã€ãã³ãã«ãã£ãŠã§ã¯ãªããå
éšã®ã»ãã·ã§ã³èªäœã®ããžãã¯ã«ãã£ãŠéãããããšãïŒãããã«ãããæ¢ã«å£ãããã€ã³ã¿ãŒã§ã®åŠçã æåã®ã¢ã€ãã¢ãããçæã§ããã®ãããªçµéšãåãåã£ãã®ã§ãå¥ã®æŠç¥ãæ¡çšãããŸããïŒepollã«ããã¡ã€ã³ãªã¹ãã³ã°ã¹ããªãŒã ã¯ããªã¹ãã³ã°ãœã±ããã®ã€ãã³ãã«ã®ã¿å¿çããçä¿¡æ¥ç¶ãåãå
¥ãããã®æ°ãåŸ
æ©ãã¥ãŒã«èš±å¯ãããŠããå ŽåãããããéããŸããã以å€ã®å Žåãåä¿¡ããæ¥ç¶ãåŠçã®ããã«ãã¥ãŒã«å
¥ããŸãã ã¯ãŒã¯ãããŒã¯ãã®ãã¥ãŒãå·®ãåŒããŠããã®ãœã±ãããepollã»ããã«å
¥ããŸãã ã¯ãŒã¯ãããŒã¯epollèšè¿°åã§åäœãããã¹ãŠã1ã€ã®ã¹ããªãŒã ã®ãã¬ãŒã ã¯ãŒã¯å
ã§è¡ãããŸãïŒepollãžã®é
眮ãããŒã¿å°çã®ã€ãã³ããžã®åå¿ãèªã¿åã/æžã蟌ã¿ãçµäºïŒãã³ãã«ãéãããããšãepollããã®åé€ã¯ã·ã¹ãã ã¬ãã«ã§èªåçã«è¡ãããŸãïŒ ã ãã®ãããªçµç¹ã®çµæãšããŠãçä¿¡æ¥ç¶ã®ãã¥ãŒãä¿è·ããåæããªããã£ãã¯1ã€ã ãã§ãã äžæ¹ã§ã¯ããªã¹ãã³ã°ã¹ããªãŒã ã®ã¿ããã®ãã¥ãŒã«æžã蟌ã¿ãä»æ¹ã§ã¯ãåä¿¡ãããæ¥ç¶ã®ããã«åä¿¡ããããããŒãéžæãããŸãã 1ã€å°ãªãåé¡ã epollæ§é ã®ãŠãŒã¶ãŒããŒã¿ã䜿çšããã»ãã·ã§ã³ãªããžã§ã¯ããžã®ãã€ã³ã¿ãŒã®ãã€ã³ããæŸæ£ããŸãã 解決çïŒé£æ³é
åã䜿çšããŸãã ããŒã¯ãœã±ããèšè¿°åã§ãããããŒã¿ã¯ã»ãã·ã§ã³ãªããžã§ã¯ãã§ãã ããã«ãããã€ãã³ããçºçãããšããepollã€ãã³ããããŠãŒã¶ãŒããŒã¿ãååŸããæ©äŒããããšãã ãã§ãªããäœããã®ããžãã¯ã«åŸã£ãŠãããšãã°ã¿ã€ã ã¢ãŠãã«ãã£ãŠæ¥ç¶ãéããå¿
èŠããããšãïŒæ¥ç¶ããŒã«ãå©çšå¯èœïŒã«ã»ãã·ã§ã³ãæäœã§ããŸãã
æåã®ãªãã·ã§ã³ã¯ãå®å
šã«1ã€ã®ãã¡ã€ã«ã«èšè¿°ãããCïŒ/ Javaéçºè
ã®ã¹ã¿ã€ã«ã§ïŒå®£èšãšå®çŸ©ã«åå²ããããšãªãïŒã1800è¡ä»¥äžã®ã³ãŒãããããŸããã ãã¹ãã¿ã¹ã¯ã«ã¯å€ãããŸããHTTPãããã³ã«ã®å®è£
ãæå°éã§ãããšããäºå®ã«ãããããããä»ã®äœãããã«HTTPããããŒã®ãã©ã¡ãŒã¿ãŒãæå°éã§åŠçããŠGET / HEADãåŠçããããã®æå°éã§ãã ããã¯ãã€ã³ãã§ã¯ãããŸããã ç¹°ãè¿ãã«ãªããŸããããã¹ãã¿ã¹ã¯ã¯åã«äœããè©Šããããã¯ãã§ããã ãã®ãœãªã¥ãŒã·ã§ã³ã§ã®ç§ã®äž»ãªé¢å¿ã¯ãHTTPãããã³ã«ã®å®è£
ã§ã¯ãªãããã«ãã¹ã¬ãããµãŒããŒã®å®è£
ãæ¥ç¶ãšã»ãã·ã§ã³ã®ç®¡çã§ããïŒã»ãã·ã§ã³ã¯ãæ¥ç¶ã«é¢é£ããåŠçã¢ã«ãŽãªãºã ãæã€è«çããŒã¿æ§é ãšããŠç解ã§ããŸãïŒã
ãã®å·šå€§ãªãã¡ã€ã«ãç Žå£ããããã€ãã®å Žæã§å®è£
ããšãããšã次ã®ããã«ãªããŸãã
class TCPServer : private Common::NonCopyable { public: TCPServer(InetAddress const &locAddr, int backlog, int maxThreadsCount, int maxConnectionsCount, UserSessionCreator sessionCreator); private: typedef std::tr1::shared_ptr<Common::IDisposable> IDisposablePtr; typedef std::vector<IDisposablePtr> IDisposablePool; Private::ClientItemQueuePtr AcceptedItems; IDisposablePool Threads; };
ããã¯ãããããç§ãèšè¿°ããªããã°ãªããªãã£ãæçã®ãµãŒããŒã¯ã©ã¹å®è£
ã§ãã ãã®ã¯ã©ã¹ã¯ããªã¹ããŒãšè€æ°ã®ã¯ãŒã«ãŒã®è€æ°ã®ã¹ã¬ããã®ã¿ãäœæãããããã®ãã«ããŒã§ãã
å®è£
TCPServer::TCPServer(InetAddress const &locAddr, int backlog, int maxThreadsCount, int maxConnectionsCount, UserSessionCreator sessionCreator) : AcceptedItems(new Private::ClientItemQueue(backlog)) { int EventsCount = maxConnectionsCount / maxThreadsCount; for (int i = 0 ; i < maxThreadsCount ; ++i) { Threads.push_back(IDisposablePtr(new Private::WorkerThread( EventsCount + (i <= maxThreadsCount - 1 ? 0 : maxConnectionsCount % maxThreadsCount), AcceptedItems ))); } Threads.push_back(IDisposablePtr(new Private::ListenThread(locAddr, backlog, AcceptedItems, sessionCreator))); }
ãŸãçŽ æŽãããã§ã¯ãããŸããã äž¡æ¹ã®ã¯ã©ã¹ã¯
ãªã¹ãã³ã°ã¹ããªãŒã class ListenThread : private TCPServerSocket , public Common::IDisposable { public: ListenThread(InetAddress const &locAddr, int backlog, ClientItemQueuePtr acceptedClients, UserSessionCreator sessionCreator) : TCPServerSocket(locAddr, backlog) , AcceptedClients(acceptedClients) , SessionCreator(sessionCreator) , Selector(1, WaitTimeout, std::tr1::bind(&ListenThread::OnSelect, this, std::tr1::placeholders::_1, std::tr1::placeholders::_2)) { Selector.AddSocket(GetHandle(), Network::ISelector::stRead); } private: enum { WaitTimeout = 100 }; ClientItemQueuePtr AcceptedClients; UserSessionCreator SessionCreator; SelectorThread Selector; void OnSelect(SocketHandle handle, Network::ISelector::SelectType selectType) {
ã ãã
ã¯ãŒã¯ãã㌠class WorkerThread : private Common::NonCopyable , public Common::IDisposable { public: WorkerThread(int maxEventsCount, ClientItemQueuePtr acceptedClients) : MaxConnections(maxEventsCount) , AcceptedClients(acceptedClients) , Selector(maxEventsCount, WaitTimeout, std::tr1::bind(&WorkerThread::OnSelect, this, std::tr1::placeholders::_1, std::tr1::placeholders::_2), SelectorThread::ThreadFunctionPtr(new SelectorThread::ThreadFunction(std::tr1::bind( &WorkerThread::OnIdle, this)))) { } private: enum { WaitTimeout = 100 }; typedef std::map<SocketHandle, ClientItemPtr> ClientPool; unsigned MaxConnections; ClientItemQueuePtr AcceptedClients; ClientPool Clients; SelectorThread Selector; void OnSelect(SocketHandle handle, Network::ISelector::SelectType selectType) {
ã€ãã³ããããŒã¯ã©ã¹ã䜿çšãã
ã»ã¬ã¯ã¿ãŒã¹ã¬ãã class SelectorThread : private EPollSelector , private System::ThreadLoop { public: using EPollSelector::AddSocket; typedef System::Thread::ThreadFunction ThreadFunction; typedef std::tr1::shared_ptr<ThreadFunction> ThreadFunctionPtr; SelectorThread(int maxEventsCount, unsigned waitTimeout, ISelector::SelectFunction onSelectFunc, ThreadFunctionPtr idleFunc = ThreadFunctionPtr()); virtual ~SelectorThread(); private: void SelectItems(ISelector::SelectFunction &func, unsigned waitTimeout, ThreadFunctionPtr idleFunc); };
ã ãã®ã¹ã¬ããã¯
EPollSelector class EPollSelector : private Common::NonCopyable , public ISelector { public: EPollSelector(int maxSocketCount); ~EPollSelector(); virtual void AddSocket(SocketHandle handle, int selectType); virtual void Select(SelectFunction *function, unsigned timeout); private: typedef std::vector<epoll_event> EventPool; EventPool Events; int EPoll; static int GetSelectFlags(int selectType); };
æ¿èªãããååç©ã®èšè¿°åã§çºçããã€ãã³ãã«å¯Ÿããåå¿ãæŽçããããã
ãµãŒããŒã®ãœãŒã¹ã¯ã©ã¹ãèŠããšããŠãŒã¶ãŒã»ãã·ã§ã³ã¯ã©ã¹ãäœæããããã®ãã¡ã³ã¯ã¿ãŒãæåŸã®ãã©ã¡ãŒã¿ãŒãšããŠæž¡ãããŠããããšãããããŸãã ãŠãŒã¶ãŒã»ãã·ã§ã³ã¯ã€ã³ã¿ãŒãã§ãŒã¹ã®å®è£
ã§ã
struct IUserSession { virtual ~IUserSession() {} virtual void Init(IConnectionCtrl *ctrl) = 0; virtual void Done() = 0; virtual unsigned GetMaxBufSizeForRead() const = 0; virtual bool IsExpiredSession(std::time_t lastActionTime) const = 0; virtual void OnRecvData(void const *buf, unsigned bytes) = 0; virtual void OnIdle() = 0; };
ãã®ã€ã³ã¿ãŒãã§ã€ã¹ã®å®è£
ã«å¿ããŠãç°ãªããããã³ã«ãå®è£
ã§ããŸãã Initã¡ãœãããšDoneã¡ãœããã¯ãããããã»ãã·ã§ã³ã®éå§æãšçµäºæã«åŒã³åºãããŸãã GetMaxBufSizeForReadã¯ãããŒã¿èªã¿åãæäœäžã«å²ãåœãŠãããæ倧ãããã¡ãŒãµã€ãºãè¿ãå¿
èŠããããŸãã èªã¿åãããããŒã¿ã¯OnRecvDataã«å«ãŸããŸãã ã»ãã·ã§ã³ãæéåãã«ãªã£ãããšãäŒããã«ã¯ãIsExpiredSessionãé©åãªæ¹æ³ã§å®è£
ããå¿
èŠããããŸãã OnIdleã¯ããã€ãã®ã¢ã¯ã·ã§ã³ã®éã«åŒã³åºãããŸããããã§ãã»ãã·ã§ã³å®è£
ã¯ããã€ãã®ããã¯ã°ã©ãŠã³ãã¢ã¯ã·ã§ã³ãå®è¡ããã€ã³ã¿ãŒãã§ã€ã¹ãä»ããŠéããããšãç®çãšããŠèªèº«ãããŒã¯ã§ããŸãã
struct IConnectionCtrl { virtual ~IConnectionCtrl() { } virtual void MarkMeForClose() = 0; virtual void UpdateSessionTime() = 0; virtual bool SendData(void const *buf, unsigned *bytes) = 0; virtual bool SendFile(int fileHandle, unsigned offset, unsigned *bytes) = 0; virtual InetAddress const& GetAddress() const = 0; virtual SocketTuner GetSocketTuner() const = 0; };
IConnectionCtrlã€ã³ã¿ãŒãã§ã€ã¹ã¯ããŠãŒã¶ãŒã»ãã·ã§ã³ããããã¯ãŒã¯ã«ããŒã¿ãéä¿¡ã§ããããã«ïŒSendDataããã³SendFileã¡ãœããïŒãéããããããã«èªèº«ãããŒã¯ã§ããããã«ïŒMarkMeForCloseã¡ãœããïŒããçããŠãããïŒUpdateSessionTimeã¡ãœããã IsExpiredSessionïŒãåãã»ãã·ã§ã³ã¯çä¿¡æ¥ç¶ïŒGetAddressã¡ãœããïŒã®ã¢ãã¬ã¹ãšãœã±ããèšå®ã®SocketTunerãªããžã§ã¯ãïŒçŸåšã®æ¥ç¶ïŒGetSocketTunerã¡ãœããïŒïŒãååŸã§ããŸãã
HTTPãããã³ã«ã®å®è£
ã¯ãHttpUserSessionã¯ã©ã¹ã«ãããŸãã äžã§èšã£ãããã«ãHTTPã®å®è£
ã¯ç§ã«ãšã£ãŠæãèå³æ·±ããåªå
床ãäœãã®ã§ãããŸãèããŸããã§ããã ç§ã¯äœãèµ·ãã£ãã®ããæžãã®ã«ååã§ãããšæ£ç¢ºã«æã£ã:)
Libeventã®å®è£
libeventã§ã®å®è£
ã¯ä»ã§ãç§ã«ãšã£ãŠãæ°ã«å
¥ãã§ãã ãã®ã©ã€ãã©ãªã«ãããéåæå
¥åºåãæŽçãããããã¯ãŒã¯ããã°ã©ãã³ã°ã®åŸ®åŠãªç¹ã®å€ããéçºè
ããé ãããšãã§ããŸãã ããã«ãããããŒã¿ããã®ä»ã®ã€ãã³ãã®åä¿¡ãéä¿¡ãããŒã¿ã®éåæéä¿¡ã®ããã®ã³ãŒã«ããã¯é¢æ°ããã³ã°ã¢ããããããšã«ãããçããŒã¿ã®åŠçãå®è£
ã§ããŸãã ããŒã¿ã®äœã¬ãã«ã®äœæ¥ã«å ããŠãé«ã¬ãã«ã®ãããã³ã«ããããŸãã libeventã«ã¯HTTPãµãŒããŒãçµã¿èŸŒãŸããŠãããããèŠæ±ããããŒã®è§£æãšåãå¿çããããŒã®çæãæœè±¡åã§ããŸãã ã©ã€ãã©ãªããã³ãã®ä»ã®æ©èœã䜿çšããŠRPCãå®è£
ããããšãã§ããŸãã
çµã¿èŸŒã¿ã䜿çšããŠHTTPãµãŒããŒãå®è£
ããå Žåãã·ãŒã±ã³ã¹ã¯æ¬¡ã®ããã«ãªããŸãã
- event_base_newãåŒã³åºããŠãããã€ãã®åºæ¬çãªãªããžã§ã¯ããäœæããŸãïŒããç°¡åãªå Žåã®ããã«åçŽåãããevent_initããããŸãïŒã ãªããžã§ã¯ããåé€ãããã¢ã®é¢æ°ã¯event_base_freeã§ãã
- evhttp_newãåŒã³åºããŠãHTTPãšã³ãžã³ãªããžã§ã¯ããäœæããŸãã evhttp_freeãªããžã§ã¯ããåé€ããããã®ãã¢é¢æ°ã
- ãã©ã°ã®çµã¿åããã§evhttp_set_allowed_methodsé¢æ°ã䜿çšããŠããµãŒããŒããµããŒãããã¡ãœãããæå®ã§ããŸãã ãããã£ãŠãããšãã°ãGETã¡ãœããã®ã¿ããµããŒãããã«ã¯ãevhttp_set_allowed_methodsïŒHttpãEVHTTP_REQ_GETïŒã®ããã«ãªããŸããããã§ãHttpã¯ã¹ãããïŒ2ïŒã§äœæãããèšè¿°åã§ãã
- evhttp_set_gencbãåŒã³åºããŠãçä¿¡èŠæ±ãåŠçããã³ãŒã«ããã¯é¢æ°ãèšå®ããŸãã
- evhttp_accept_socketé¢æ°ãåŒã³åºããŠããªã¹ãã³ã°ãœã±ãããHTTPãµãŒããŒãªããžã§ã¯ãã®ã€ã³ã¹ã¿ã³ã¹ã«é¢é£ä»ããŸãã ãªã¹ãã³ã°ãœã±ããã¯ãåããœã±ãã/ãã€ã³ã/ãªã¹ã³ãä»ããŠäœæããã³æ§æã§ããŸãã
- event_base_loopé¢æ°ãåŒã³åºããŠãã€ãã³ãã«ãŒããéå§ããŸãã event_base_dispatchãšããç°¡åãªãªãã·ã§ã³ããããŸãã event_base_loopã¯ã«ãŒãã§åŒã³åºãå¿
èŠããããŸãã ãã®é¢æ°ã¯ãã€ã³ã¹ããŒã«ãããã³ãŒã«ããã¯é¢æ°ãžã®åŒã³åºããè¡ãããã©ã€ãã©ãªã®è
žå
ã§äœãæçšãªããšãè¡ãããäœãããå¿
èŠããªãå Žåã«å¶åŸ¡ãè¿ãããã®æç¹ã§äœã䟿å©ãªããšãã§ããŸãã ãŸããã¡ãã»ãŒãžåŠçãµã€ã¯ã«ã®å¯¿åœãããç°¡åã«å¶åŸ¡ããããšãå¯èœã«ãªããŸãã
- ãªã¯ãšã¹ããã³ãã©ã§ã¯ãevbuffer_add_printfãåŒã³åºããŠããã¹ãããŒã¿ãéä¿¡ããããã©ã€ãã©ãªã«ãã¡ã€ã«èšè¿°åãæå®ããŠãevbuffer_add_fileãåŒã³åºããŠéä¿¡ããããšãã§ããŸãã ãããã®é¢æ°ã¯ãèªåã§äœæããïŒæéå
ã«åé€ããããšãå¿ããªãã§ãã ããïŒããèŠæ±ãã£ãŒã«ãevhttp_request :: output_bufferã䜿çšã§ãããããã¡ãŒãªããžã§ã¯ãã§åäœããŸãã ãã¹ãŠã®é
åã¯ããããã®é¢æ°ãéåæã§ãããšããããšã§ãã ãã¡ã€ã«ãéä¿¡ããäŸã§ã¯ããã¡ã€ã«èšè¿°åãåãevbuffer_add_fileã«æž¡ããšãããã«å¶åŸ¡ãè¿ããããã¡ã€ã«ãéä¿¡ãããåŸããã¡ã€ã«èªäœãéããããŸãã
ãã¹ãŠã1ã€ã®ã¹ã¬ããã§éåžžã«çŸãããªããŸãããå€æããããã«ããã«ãã¹ã¬ãããµãŒããŒãäœæããããšãé£ãããããŸããã boost ::ã¹ã¬ããããŸãã¯ã¹ããªãŒã ã®äœæ¥ãã«ãã»ã«åããã¯ãã¹ãã©ãããã©ãŒã ã¯ã©ã¹ãªã©ã䜿çšãããšãlibeventã¯ã¯ãã¹ãã©ãããã©ãŒã ã©ã€ãã©ãªã§ãããããå®å
šã«ã¯ãã¹ãã©ãããã©ãŒã ã®ãœãªã¥ãŒã·ã§ã³ãååŸã§ããŸãã ç§èªèº«ã®å®è£
ã§ã¯ãLinuxã®ã¹ããªãŒã ã«å¯ŸããŠã®ã¿ã©ãããŒã䜿çšããŸãã ããããããã¯ããã»ã©éèŠã§ã¯ãããŸããã
åã¯ãŒã¯ãããŒã®ã¡ã€ã³ã¹ã¬ããã¯ãç¬èªã®èšè¿°åãäœæããå¿
èŠããããŸãã æé 1ã5ãå®äºããŸãã ã¯ãŒã¯ãããŒã¯ãã¡ãã»ãŒãžåŠçãµã€ã¯ã«ã®ã¿ããããå¿
èŠããããŸã-ã¹ããã6ãåã¯ãŒã¯ãããŒã§ã¹ããã7ãå®è¡ãããŸãã èŠçŽãããšã1ã€ã®ãªã¹ãã³ã°ãœã±ãããäœæãããã®åŠçãè€æ°ã®ã¯ãŒã«ãŒã¹ã¬ããã«èª²ããŸãã
ãã®ãããå®è£
ã§ã¯ãã¹ããªãŒã ããã¡ã€ã«ãããã³ã³ãã³ãã©ã€ã³è§£æçšã®ããªããã£ããæ¢ã«ããã€ããããããCïŒ/ Javaã¹ã¿ã€ã«ã§çŽ200è¡ã®GETã¡ãœããã®ã¿ããµããŒãããHTTPãµãŒããŒãååŸããŸããã èµ·ãã£ãŠããããšãå®å
šã«å¶åŸ¡ããŠã³ãŒããèšè¿°ããäœæ¥ã®ãã®åæžã¯ãåã°ããããšã§ãã ããã«ã䞻芳çã«ãçµæã®ãµãŒããŒã¯å°ãéãåäœããŸãããæåŸã«ãã¹ããèŠãŠã¿ãŸããã...
libeventã§ã®HTTPãµãŒããŒã®å®è£
#include <event.h> #include <evhttp.h> #include <unistd.h> #include <string.h> #include <signal.h> #include <vector> #include <iostream> #include <tr1/functional> #include <tr1/memory> #include "tcp_server_socket.h" #include "inet_address_v4.h" #include "thread.h" #include "command_line.h" #include "logger.h" #include "file_holder.h" namespace Network { namespace Private { DECLARE_RUNTIME_EXCEPTION(EventBaseHolder) class EventBaseHolder : private Common::NonCopyable { public: EventBaseHolder() : EventBase(event_base_new()) { if (!EventBase) throw EventBaseHolderException("Failed to create new event_base"); } ~EventBaseHolder() { event_base_free(EventBase); } event_base* GetBase() const { return EventBase; } private: event_base *EventBase; }; DECLARE_RUNTIME_EXCEPTION(HttpEventHolder) class HttpEventHolder : public EventBaseHolder { public: typedef std::tr1::function<void (char const *, evbuffer *)> RequestHandler; HttpEventHolder(SocketHandle sock, RequestHandler const &handler) : Handler(handler) , Http(evhttp_new(GetBase())) { evhttp_set_allowed_methods(Http, EVHTTP_REQ_GET); evhttp_set_gencb(Http, &HttpEventHolder::RawHttpRequestHandler, this); if (evhttp_accept_socket(Http, sock) == -1) throw HttpEventHolderException("Failed to accept socket for http"); } ~HttpEventHolder() { evhttp_free(Http); } private: RequestHandler Handler; evhttp *Http; static void RawHttpRequestHandler(evhttp_request *request, void *prm) { reinterpret_cast<HttpEventHolder *>(prm)->ProcessRequest(request); } void ProcessRequest(evhttp_request *request) { try { Handler(request->uri, request->output_buffer); evhttp_send_reply(request, HTTP_OK, "OK", request->output_buffer); } catch (std::exception const &e) { evhttp_send_reply(request, HTTP_INTERNAL, e.what() ? e.what() : "Internal server error.", request->output_buffer); } } }; class ServerThread : private HttpEventHolder , private System::Thread { public: ServerThread(SocketHandle sock, std::string const &rootDir, std::string const &defaultPage) : HttpEventHolder(sock, std::tr1::bind(&ServerThread::OnRequest, this, std::tr1::placeholders::_1, std::tr1::placeholders::_2)) , Thread(std::tr1::bind(&ServerThread::DispatchProc, this)) , RootDir(rootDir) , DefaultPage(defaultPage) { } ~ServerThread() { IsRun = false; } private: enum { WaitTimeout = 10000 }; bool volatile IsRun; std::string RootDir; std::string DefaultPage; void DispatchProc() { IsRun = true; while(IsRun) { if (event_base_loop(GetBase(), EVLOOP_NONBLOCK)) { Common::Log::GetLogInst() << "Failed to run dispatch events"; break; } usleep(WaitTimeout); } } void OnRequest(char const *resource, evbuffer *outBuffer) { std::string FileName; GetFullFileName(resource, &FileName); try { System::FileHolder File(FileName); if (!File.GetSize()) { evbuffer_add_printf(outBuffer, "Empty file"); return; } evbuffer_add_file(outBuffer, File.GetHandle(), 0, File.GetSize()); File.Detach(); } catch (System::FileHolderException const &) { evbuffer_add_printf(outBuffer, "File not found"); } } void GetFullFileName(char const *resource, std::string *fileName) const { fileName->append(RootDir); if (!resource || !strcmp(resource, "/")) { fileName->append("/"); fileName->append(DefaultPage); } else { fileName->append(resource); } } }; } class HTTPServer : private TCPServerSocket { public: HTTPServer(InetAddress const &locAddr, int backlog, int maxThreadsCount, std::string const &rootDir, std::string const &defaultPage) : TCPServerSocket(locAddr, backlog) { for (int i = 0 ; i < maxThreadsCount ; ++i) { ServerThreads.push_back(ServerThreadPtr(new Private::ServerThread(GetHandle(), rootDir, defaultPage))); } } private: typedef std::tr1::shared_ptr<Private::ServerThread> ServerThreadPtr; typedef std::vector<ServerThreadPtr> ServerThreadPool; ServerThreadPool ServerThreads; }; } int main(int argc, char const **argv) { if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { std::cerr << "Failed to call signal(SIGPIPE, SIG_IGN)" << std::endl; return 0; } try { char const ServerAddr[] = "Server"; char const ServerPort[] = "Port"; char const MaxBacklog[] = "Backlog"; char const ThreadsCount[] = "Threads"; char const RootDir[] = "Root"; char const DefaultPage[] = "DefaultPage"; // Server:127.0.0.1 Port:5555 Backlog:10 Threads:4 Root:./ DefaultPage:index.html Common::CommandLine CmdLine(argc, argv); Network::HTTPServer Srv( Network::InetAddressV4::CreateFromString( CmdLine.GetStrParameter(ServerAddr), CmdLine.GetParameter<unsigned short>(ServerPort)), CmdLine.GetParameter<unsigned>(MaxBacklog), CmdLine.GetParameter<unsigned>(ThreadsCount), CmdLine.GetStrParameter(RootDir), CmdLine.GetStrParameter(DefaultPage) ); std::cin.get(); } catch (std::exception const &e) { Common::Log::GetLogInst() << e.what(); } return 0; }
boost.asioã§ã®å®è£
boost.asioã¯boostã®äžéšã§ããããããã¯ãŒã¯ã¢ããªã±ãŒã·ã§ã³ãããã³ã¯ãã¹ãã©ãããã©ãŒã ã¢ããªã±ãŒã·ã§ã³ã®éçºã倧å¹
ã«åæžããã®ã«åœ¹ç«ã¡ãŸãã ã©ã€ãã©ãªã¯ãéçºè
ããå€ãã®ã«ãŒãã³ãé ããŸãã
ããŒã¹ãã§HTTPãµãŒããŒã®å®è£
ãäœæããŸããã§ããã å®æããäŸãboost.asioã«åããŸããã
ãã«ãã¹ã¬ããHTTPãµãŒããŒã®äŸã HTTPãµãŒããŒ3ãã®äŸã®å®è£
ã¯ãäžèšã®äŸãšçµã¿åããããã¹ãã«éåžžã«é©ããŠããŸãã
ãã¹ãçšã®HTTPãµãŒããŒã®å®è£
ããããŸãããäžè¬çãªååã«ã€ããŠè©±ãã®ã¯æªããããŸãã...æ®å¿µãªãããlibeventãšã¯ç°ãªããboost.asioã¯HTTPãªã©ã«é¡äŒŒããé«ã¬ãã«ã®ãããã³ã«ããµããŒãããŠããŸããã ãã®å Žåãã©ã€ãã©ãªã¯TCPãä»ãããããã¯ãŒã¯ã§ã®äœæ¥ãé ããŸããããããã³ã«ããããŒãåéããã³è§£æããã«ã¯ãHTTPã®å®è£
ãéçºè
èªèº«ãè¡ãå¿
èŠããããŸãã
以äžã¯ããã®ãããã¯ã«ç
§ãããŠHTTPããããŒã解æ/åéããã®ã¯ããŸãé¢çœããªãã®ã§ã説æä»ãã®ãã«ãã¹ã¬ãããšã³ãŒãµãŒããŒã®å°ããªäŸã§ãã boost.asioã䜿çšããŠãã«ãã¹ã¬ãããµãŒããŒãäœæããæé ã¯æ¬¡ã®ãšããã§ãã
- boost :: asio :: io_serviceããã³boost :: asio :: ip :: tcp ::ã¢ã¯ã»ãã¿ãŒã¯ã©ã¹ã®ãªããžã§ã¯ããäœæããŸãã
- boost :: asio :: ip :: tcp :: resolverããã³boost :: asio :: ip :: tcp ::ãšã³ããã€ã³ãã䜿çšãããšããªã¹ãã³ã°ãœã±ããããã€ã³ããããããŒã«ã«ã¢ãã¬ã¹ãã©ã€ãã©ãªã§äœ¿çšãããæ§é ã«å€æãããŸãã
- bindãåŒã³åºããŠãã¯ã©ã¹boost :: asio :: ip :: tcp :: acceptorã®ãªããžã§ã¯ãã§ãªãã¹ã³ããŸãã
- ã¯ã©ã¹ãæ¥ç¶ããäœæããŸãã å¥åãã»ãã·ã§ã³ããçä¿¡ãŠãŒã¶ãŒæ¥ç¶ãåä¿¡ãããšãã«ãã®ã€ã³ã¹ã¿ã³ã¹ã䜿çšãããŸãã
- é©åãªã³ãŒã«ããã¯é¢æ°ãæ§æããŠãçä¿¡æ¥ç¶ãåä¿¡ããããŒã¿ãåä¿¡ããŸãã
- boost :: asio :: io_service :: runãåŒã³åºããŠãã¡ãã»ãŒãžåŠçã«ãŒããéå§ããŸãã
ãŸããlibeventã®äŸãšåæ§ã«ããã«ãã¹ã¬ãããµãŒããŒã¯ãäžèšã®äžé£ã®æé ã䜿çšããŠã·ã³ã°ã«ã¹ã¬ãããµãŒããŒããéåžžã«ç°¡åã«äœæã§ããŸãã ãã®å Žåãã·ã³ã°ã«ã¹ã¬ãããµãŒããŒãšãã«ãã¹ã¬ãããµãŒããŒã®éãã¯ããã«ãã¹ã¬ããå®è£
ã®åã¹ã¬ããã§boost :: asio :: io_service :: runã¡ãœãããåŒã³åºãå¿
èŠãããããšã ãã§ãã
boost.asioã§ã®ãšã³ãŒãµãŒããŒã®å®è£
#include <boost/noncopyable.hpp> #include <boost/asio.hpp> #include <boost/shared_ptr.hpp> #include <boost/thread.hpp> #include <boost/make_shared.hpp> #include <boost/bind.hpp> #include <boost/enable_shared_from_this.hpp> #include <boost/array.hpp> namespace Network { namespace Private { class Connection : private boost::noncopyable , public boost::enable_shared_from_this<Connection> { public: Connection(boost::asio::io_service &ioService) : Strand(ioService) , Socket(ioService) { } boost::asio::ip::tcp::socket& GetSocket() { return Socket; } void Start() { Socket.async_read_some(boost::asio::buffer(Buffer), Strand.wrap( boost::bind(&Connection::HandleRead, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred) )); } void HandleRead(boost::system::error_code const &error, std::size_t bytes) { if (error) return; std::vector<boost::asio::const_buffer> Buffers; Buffers.push_back(boost::asio::const_buffer(Buffer.data(), bytes)); boost::asio::async_write(Socket, Buffers, Strand.wrap( boost::bind(&Connection::HandleWrite, shared_from_this(), boost::asio::placeholders::error) )); } void HandleWrite(boost::system::error_code const &error) { if (error) return; boost::system::error_code Code; Socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, Code); } private: boost::array<char, 4096> Buffer; boost::asio::io_service::strand Strand; boost::asio::ip::tcp::socket Socket; }; } class EchoServer : private boost::noncopyable { public: EchoServer(std::string const& locAddr, std::string const& port, unsigned threadsCount) : Acceptor(IoService) , Threads(threadsCount) { boost::asio::ip::tcp::resolver Resolver(IoService); boost::asio::ip::tcp::resolver::query Query(locAddr, port); boost::asio::ip::tcp::endpoint Endpoint = *Resolver.resolve(Query); Acceptor.open(Endpoint.protocol()); Acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); Acceptor.bind(Endpoint); Acceptor.listen(); StartAccept(); std::generate(Threads.begin(), Threads.end(), boost::bind( &boost::make_shared<boost::thread, boost::function<void ()> const &>, boost::function<void ()>(boost::bind(&boost::asio::io_service::run, &IoService)) )); } ~EchoServer() { std::for_each(Threads.begin(), Threads.end(), boost::bind(&boost::asio::io_service::stop, &IoService)); std::for_each(Threads.begin(), Threads.end(), boost::bind(&boost::thread::join, _1)); } private: boost::asio::io_service IoService; boost::asio::ip::tcp::acceptor Acceptor; typedef boost::shared_ptr<Private::Connection> ConnectionPtr; ConnectionPtr NewConnection; typedef boost::shared_ptr<boost::thread> ThreadPtr; typedef std::vector<ThreadPtr> ThreadPool; ThreadPool Threads; void StartAccept() { NewConnection = boost::make_shared<Private::Connection, boost::asio::io_service &>(IoService); Acceptor.async_accept(NewConnection->GetSocket(), boost::bind(&EchoServer::HandleAccept, this, boost::asio::placeholders::error)); } void HandleAccept(boost::system::error_code const &error) { if (!error) NewConnection->Start(); StartAccept(); } }; } int main() { try { Network::EchoServer Srv("127.0.0.1", "5555", 4); std::cin.get(); } catch (std::exception const &e) { std::cerr << e.what() << std::endl; } return 0; }
ãã¹ãäž
åãåã£ãå·¥èžåãæ¯èŒããæãæ¥ãŸãã...
ãã¹ãŠãéçºããã³ãã¹ãããããã©ãããã©ãŒã ã¯ã4GBã®RAMãšUbuntu 12.04ãã¹ã¯ããããå®è¡ãã2ã³ã¢ããã»ããµãæèŒããéåžžã®ã©ãããããã§ãã
ãŸãããã¹ãçšã®ãŠãŒãã£ãªãã£ãé
眮ããŸãã
sudo apt-get install apache2-utils
ãã®æ¹æ³ã§ãã¹ãããŸãïŒ
ab -c 100 -k -r -t 5 "http://127.0.0.1:5555/test.jpg"
ãã¹ãŠã®ãµãŒããŒã«ã€ããŠã4ã€ã®ã¯ãŒã¯ãããŒã100ã®äžŠåæ¥ç¶ã2496629ãã€ãã®éä¿¡çšãã¡ã€ã«ãããã³5ç§ã®æšå®æéééãèšå®ãããŸããã
çµæïŒ
Epollã®å®è£
ãã³ãããŒã¯127.0.0.1ïŒå¿è匷ãïŒ
å®äºãã2150ãªã¯ãšã¹ã
ãµãŒããŒãœãããŠã§ã¢ïŒMyTestHttpServer
ãµãŒããŒã®ãã¹ãåïŒ127.0.0.1
ãµãŒããŒããŒãïŒ5555
ããã¥ã¡ã³ããã¹ïŒ/test.jpg
ããã¥ã¡ã³ãã®é·ãïŒ2496629ãã€ã
åæå®è¡ã¬ãã«ïŒ100
ãã¹ãã«ããã£ãæéïŒ5.017ç§
å®å
šãªãªã¯ãšã¹ãïŒ2150
倱æãããªã¯ãšã¹ãïŒ0
æžã蟌ã¿ãšã©ãŒïŒ0
ããŒãã¢ã©ã€ãèŠæ±ïŒ0
転éãããåèšïŒ5389312814ãã€ã
転éãããHTMLïŒ5388981758ãã€ã
1ç§ãããã®ãªã¯ãšã¹ãïŒ428.54 [ïŒ/ sec]ïŒå¹³åïŒ
ãªã¯ãšã¹ããããã®æéïŒ233.348 [ms]ïŒå¹³åïŒ
ãªã¯ãšã¹ããããã®æéïŒ2.333 [ms]ïŒå¹³åããã¹ãŠã®åæãªã¯ãšã¹ãå
šäœïŒ
転éé床ïŒ1049037.42 [ãããã€ã/ç§]åä¿¡
æ¥ç¶æéïŒããªç§ïŒ
æå°å¹³å[±sd]æ倧äžå€®å€
æ¥ç¶ïŒ0 0 0.5 0 3
åŠçïŒ74226 58.2 229 364
åŸ
æ©äžïŒ2 133 64.8 141 264
åèšïŒ77226 58.1 229 364
Libeventã®å®è£
ãã³ãããŒã¯127.0.0.1ïŒå¿è匷ãïŒ
å®äºãã1653ãªã¯ãšã¹ã
ãµãŒããŒãœãããŠã§ã¢ïŒ
ãµãŒããŒã®ãã¹ãåïŒ127.0.0.1
ãµãŒããŒããŒãïŒ5555
ããã¥ã¡ã³ããã¹ïŒ/test.jpg
ããã¥ã¡ã³ãã®é·ãïŒ2496629ãã€ã
åæå®è¡ã¬ãã«ïŒ100
ãã¹ãã«ããã£ãæéïŒ5.008ç§
å®å
šãªãªã¯ãšã¹ãïŒ1653
倱æãããªã¯ãšã¹ãïŒ0
æžã蟌ã¿ãšã©ãŒïŒ0
ããŒãã¢ã©ã€ããªã¯ãšã¹ãïŒ1653
転éãããåèšïŒ4263404830ãã€ã
転éãããHTMLïŒ4263207306ãã€ã
1ç§ãããã®ãªã¯ãšã¹ãïŒ330.05 [ïŒ/ç§]ïŒå¹³åïŒ
ãªã¯ãšã¹ããããã®æéïŒ302.987 [ms]ïŒå¹³åïŒ
ãªã¯ãšã¹ããããã®æéïŒ3.030 [ms]ïŒå¹³åããã¹ãŠã®åæãªã¯ãšã¹ãå
šäœïŒ
転éé床ïŒ831304.15 [ãããã€ã/ç§]åä¿¡
æ¥ç¶æéïŒããªç§ïŒ
æå°å¹³å[±sd]æ倧äžå€®å€
æ¥ç¶ïŒ0 53 223.3 0 1000
åŠçïŒ3 228 275.5 62 904
åŸ
æ©äžïŒ0 11 42.5 5 639
åèšïŒ3 280 417.9 62 1864
boost.asioã§ã®å®è£
ãã³ãããŒã¯127.0.0.1ïŒå¿è匷ãïŒ
çµäºãã639ãªã¯ãšã¹ã
ãµãŒããŒãœãããŠã§ã¢ïŒ
ãµãŒããŒã®ãã¹ãåïŒ127.0.0.1
ãµãŒããŒããŒãïŒ5555
ããã¥ã¡ã³ããã¹ïŒ/test.jpg
ããã¥ã¡ã³ãã®é·ãïŒ2496629ãã€ã
åæå®è¡ã¬ãã«ïŒ100
ãã¹ãã«ããã£ãæéïŒ5.001ç§
å®å
šãªãªã¯ãšã¹ãïŒ639
倱æãããªã¯ãšã¹ãïŒ0
æžã蟌ã¿ãšã©ãŒïŒ0
ããŒãã¢ã©ã€ãèŠæ±ïŒ0
転éãããåèšïŒ1655047414ãã€ã
転éãããHTMLïŒ1654999464ãã€ã
1ç§ãããã®ãªã¯ãšã¹ãïŒ127.78 [ïŒ/ sec]ïŒå¹³åïŒ
ãªã¯ãšã¹ããããã®æéïŒ782.584 [ms]ïŒå¹³åïŒ
ãªã¯ãšã¹ããããã®æéïŒ7.826 [ms]ïŒå¹³åããã¹ãŠã®åæãªã¯ãšã¹ãå
šäœïŒ
転éé床ïŒ323205.36 [Kãã€ã/ç§]åä¿¡
æ¥ç¶æéïŒããªç§ïŒ
æå°å¹³å[±sd]æ倧äžå€®å€
æ¥ç¶ïŒ0 0 1.1 0 4
åŠçïŒ286 724 120.0 689 1106
åŸ
æ©äžïŒ12 364 101.0 394 532
åèšïŒ286724 120.0 689 1106
çµæã¯è¡šã«ãŸãšããããŠããŸãã
| ãšããŒã« | libevent | boost.asio |
å®å
šãªãªã¯ãšã¹ã | 2150 | 1653 | 639 |
転éãããåèšïŒãã€ãïŒ | 5389312814 | 4263404830 | 1655047414 |
転éãããHTMLïŒãã€ãïŒ | 5388981758 | 4263207306 | 1654999464 |
1ç§ãããã®ãªã¯ãšã¹ã[ç§]ïŒå¹³åïŒ | 428.54 | 330.05 | 127.78 |
ãªã¯ãšã¹ããããã®æé[ms]ïŒå¹³åïŒ | 233.348 | 302.987 | 782.584 |
åä¿¡ãã転éé床[ãããã€ã/ç§] | 1049037.42 | 831304.15 | 323205.36 |
åã«ã¯ãåãé²éªšãªåãçµ±èšã®3çš®é¡ããããŸãã èªããããåŸãªãããçµæã¯ç§ãåã°ããããåŸãªãã çµæã«ç¹å¥ãªæ³šæãæãã¹ãã§ã¯ãªããšæããŸããããµãŒããŒãœãããŠã§ã¢çšã®éçºããŒã«ã®éžæã決å®ããéã«åœ¹ç«ã€ãããããªããµããŒãæ
å ±ãšããŠããããèŠãããšãã§ããŸãã çµæãæ£ç¢ºã«ããããã«ããµãŒããŒããŒããŠã§ã¢äžã§è€æ°ã®å®è¡ããããã¯ãŒã¯äžã®ä»ã®ãã·ã³ã§å®è¡äžã®ã¯ã©ã€ã¢ã³ããªã©ãé
眮ããããšããå§ãããŸãã
100䞊åã¯ãšãª-ããã¯å°ããããã«èŠããŸããããã®ãããªæ§ãããªæ¡ä»¶ã§ãã¹ãããã«ã¯ååã§ãã ãã¡ãããäœåãã®äžŠåã¯ãšãªã®çµæã確èªãããã®ã§ããããã§ã«ä»ã®èŠå ããããŸãã ãã®ãããªèŠå ã®1ã€ã¯ãããã»ã¹ã§åæã«éãããšãã§ãããã¡ã€ã«èšè¿°åã®æ°ã§ãã getrlimitããã³setrlimité¢æ°ãåŒã³åºãããšã«ãããããã€ãã®ããã»ã¹ãã©ã¡ãŒã¿ãèŠã€ããŠèšå®ã§ããŸãã ããã»ã¹ããšã«å²ãåœãŠãããŠãããã¡ã€ã«èšè¿°åã®æ°ã調ã¹ãã«ã¯ãrlimitæ§é äœã®ãã©ã°RLIMIT_NOFILEãæå®ããŠgetrlimitãåŒã³åºãããšãã§ããŸãã ãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã®å Žåããããã¯ããã©ã«ãã§ããã»ã¹ããšã«1024åã®ãã¡ã€ã«èšè¿°åã§ãããããã»ã¹ã«èšå®ã§ããæ倧4096åã§ãã ⊠, , .
LinuxWebServer «» , , . . , - , - , - - . , epoll . , , . « », , , C++, C, stl, .
, libevent, , , , . .
, boost . . boost.asio . «» , , .
Linux (aio) , «» .
SVN . , . ãããïŒ , .
« » , , â , â , â . :)
«» API .
ãæž
èŽããããšãããããŸããïŒ