ã¿ãªããããã«ã¡ã¯ïŒ
John Torjoã®æ¬Boost.Asio C ++ Network Programmingã®ç¿»èš³ãç¶ããŠããŸãã
å
容ïŒ
ãã®ç« ã§ã¯ãBoost.Asioã®ããŸãç¥ãããŠããªãæ©èœã®ããã€ããèŠãŠãããŸãã stdã¹ããªãŒã ãšstreambufãªããžã§ã¯ãã¯ã䜿çšããã®ãå°ãé£ããå ŽåããããŸãããèªåã§ãããããã«ããããã«ã¯å©ç¹ããããŸãã æåŸã«ãBoost.Asioãžã®ããªãé
ãè¿œå ã衚瀺ãããŸããã³ã«ãŒãã³ã䜿çšãããšãéåæã³ãŒããäœæã§ããŸãããèªã¿ãããïŒåæã®ããã«ïŒ ããã¯éåžžã«çŽ æŽãããæ©èœã§ãã
stdã¹ããªãŒã ããã³stdå
¥å/åºåãããã¡ãŒ
ãã®ã»ã¯ã·ã§ã³ã§èšè¿°ãããŠããããšãç解ããã«ã¯ãSTLã¹ããªãŒã ãSTL streambufãªã©ã®ãªããžã§ã¯ãã«ç²ŸéããŠããå¿
èŠããããŸãã
Boost.Asioã«ã¯ãI / Oãæäœããããã®2çš®é¡ã®ãããã¡ãŒããããŸãã
- boost :: asio :: bufferïŒïŒ
- ããŒã¹ã:: asio :: streambuf
ãã®æ¬ãéããŠãåºæ¬çã«æ¬¡ã®ãããªãã®ãèŠãŸããã
size_t read_complete(boost::system::error_code, size_t bytes){ ... } char buff[1024]; read(sock, buffer(buff), read_complete); write(sock, buffer("echo\n"));
éåžžãããã§ååã§ãã ãã ããããæè»æ§ãå¿
èŠãªå Žåã¯ã
streambuf
ã䜿çšã§ããŸãã 以äžã¯ã
streambuf
ãªããžã§ã¯ãã§ã§ããæãåçŽã§ææªãªããšã§ãã
streambuf buf; read(sock, buf);
ãã®èªã¿åãã¯ã
streambuf
ãªããžã§ã¯ãã
streambuf
ã«ãªããŸã§ç¶ããŸã
streambuf
ãªããžã§ã¯ãã¯ãããå€ãã®ã¹ããŒã¹ãå容ããããã«ããèªäœãåé
åžã§ãããããåºæ¬çã«ãæ¥ç¶ãéãããããŸã§èªã¿åããè¡ãããŸãã
read_until
é¢æ°ã䜿çšããŠãæåŸã®æåãŸã§èªã¿åãããšãã§ããŸãã
streambuf buf; read_until(sock, buf, "\n");
ããã§ãèªã¿åãã¯æåã\ nããŸã§é²ã¿ãèªã¿åããããã®ããããã¡ã«è¿œå ãããèªã¿åãæ©èœãçµäºããŸãã
streambuf
ãªããžã§ã¯ãã«äœããæžã蟌ãã«ã¯ã次ã®ãããªããšãè¡ããŸãã
streambuf buf; std::ostream out(&buf); out << "echo" << std::endl; write(sock, buf);
ãšãŠãç°¡åã§ããSTLã¹ããªãŒã ãäœæããæ§ç¯äžã«streambufãªããžã§ã¯ããããã«é
眮ããéä¿¡ãããã¡ãã»ãŒãžã
write
ããã
write
é¢æ°ã䜿çšããŠãããã¡ãŒã®å
容ãéä¿¡ããå¿
èŠããããŸãã
Boost.Asioããã³STLã¹ããªãŒã
C Boost.Asioã¯ãSTLã¹ããªãŒã ãšãããã¯ãŒã¯ãçµ±åããŠçŽ æŽãããä»äºãããŸããã ã€ãŸããSTLããã§ã«åºã䜿çšããŠããå Žåã¯ããªãŒããŒããŒããããæŒç®å>>ããã³<<ãå«ãå€ãã®ã¯ã©ã¹ãæ¢ã«ããã¯ãã§ãã ãœã±ãããžã®èªã¿æžãã¯ãå
¬åãæ£æ©ãããããé
åçã§ãã
次ã®ã³ãŒãã¹ããããããããšããŸãã
struct person { std::string first_name, last_name; int age; }; std::ostream& operator<<(std::ostream & out, const person & p) { return out << p.first_name << " " << p.last_name << " " << p.age; } std::istream& operator>>(std::istream & in, person & p) { return in >> p.first_name >> p.last_name >> p.age; }
ãããã¯ãŒã¯ãä»ãã人éã®ããŒã¿ã®è»¢éã¯ã以äžã«ç€ºãããã«ç°¡åã§ãã
streambuf buf; std::ostream out(&buf); person p;
å察åŽã§ãåãããã«ç°¡åã«èªãããšãã§ããŸãã
read_until(sock, buf, "\n"); std::istream in(&buf); person p; in >> p;
streambuf
ãªããžã§ã¯ããšãã¡ãã察å¿ãã
std::ostream
ãæžã蟌ã¿ãŸãã¯
std::istream
ãèªã¿åãã«äœ¿çšããããšã®æ¬åœã«è¯ãé¢ã¯ãéåžžãšèŠãªãããã³ãŒããæžãããšã«ãªããŸãã
- ãããã¯ãŒã¯ãä»ããŠéä¿¡ããããã®ãäœæããå Žåãè€æ°ã®ããŒã¿ãååšããå¯èœæ§ãéåžžã«é«ããªããŸãã ãããã£ãŠãæåŸã«ãããŒã¿ããããã¡ã«è¿œå ããŸãã ãã®ããŒã¿ãæååã§ãªãå Žåã¯ããŸãæååã«å€æããå¿
èŠããããŸãã ããã¯ãã¹ãŠã<<æŒç®åã䜿çšãããšããã©ã«ãã§çºçããŸãã
- ã¡ãã»ãŒãžãèªããšããå察åŽã§ãåãããšãèµ·ãããŸãã ããã解æããå¿
èŠããããŸããã€ãŸããäžåºŠã«1ã€ã®ããŒã¿ãèªã¿åããŸããããŒã¿ãæååã§ãªãå Žåã¯ãå€æããå¿
èŠããããŸãã ããã¯ãã¹ãŠãèªã¿åãæã«>>æŒç®åã䜿çšãããšããã©ã«ãã§çºçããŸãã
æåŸã«ã次ã®ã³ãŒãã䜿çšããŠãã³ã³ãœãŒã«ã«
streambuf
ãªããžã§ã¯ãã®å
容ããã³ãããéåžžã«ã¯ãŒã«ãªããªãã¯ãç¥ãããŠããŸãã
streambuf buf; ... std::cout << &buf << std::endl;
åæ§ã«ãã³ã³ãã³ããæååã«å€æããã«ã¯ã次ã®ã³ãŒãã¹ããããã䜿çšããŸãã
std::string to_string(streambuf &buf) { std::ostringstream out; out << &buf; return out.str(); }
ã¯ã©ã¹streambuf
åè¿°ããããã«ã
streambuf
std::streambuf.
ãã掟çããŠã
std::streambuf.
std :: streambufã®ããã«ãã³ããŒã³ã³ã¹ãã©ã¯ã¿ãŒã¯ãããŸããã
ããã«ã次ã®ãããªããã€ãã®è¿œå æ©èœããããŸãã
streambuf ([max_size,] [allocator])
ïŒãã®é¢æ°ã¯ã streambufãªããžã§ã¯ããäœæããŸãã å¿
èŠã«å¿ããŠããªãã·ã§ã³ã§ã¡ã¢ãªã®å²ãåœãŠ/解æŸã«äœ¿çšãããæ倧ãããã¡ãµã€ãºãšã¢ãã±ãŒã¿ãèšå®ã§ããŸããprepare(n)
ïŒãã®é¢æ°ã¯ã n
æåã®é£ç¶ã·ãŒã±ã³ã¹ãé
眮ããããã«äœ¿çšããããµããããã¡ãŒãè¿ããŸãã èªã¿åããŸãã¯æžã蟌ã¿ã«äœ¿çšã§ããŸãã ãã®é¢æ°ã®çµæã¯ã streambuf
ãªããžã§ã¯ãã§æ©èœããé¢æ°ã ãã§ãªããèªã¿åã/æžã蟌ã¿ãè¡ãBoost.Asioã®ç¬ç«ããé¢æ°ã§äœ¿çšã§ããŸããdata()
ïŒãã®é¢æ°ã¯ããããã¡ãŒå
šäœãé£ç¶ããæåã·ãŒã±ã³ã¹ãšããŠè¿ããæžã蟌ã¿ã«äœ¿çšãããŸãã ãã®é¢æ°ã®çµæã¯ã streambuf
ãªããžã§ã¯ãã§æ©èœããé¢æ°ã ãã§ãªããèšé²ããBoost.Asioã®ä»»æã®ç¬ç«ããé¢æ°ã§äœ¿çšã§ããŸããconsume(n)
ïŒãã®é¢æ°ã§ã¯ãããŒã¿ã¯ïŒèªã¿åãæäœããïŒå
¥åã·ãŒã±ã³ã¹ããåé€ãããŸããcommit(n)
ïŒãã®é¢æ°ã§ã¯ãããŒã¿ã¯åºåã·ãŒã±ã³ã¹ïŒæžã蟌ã¿æäœïŒããåé€ãããå
¥åã·ãŒã±ã³ã¹ïŒèªã¿åãæäœïŒã«è¿œå ãããŸããsize()
ïŒãã®é¢æ°ã¯ã streambuf
ãªããžã§ã¯ãå
šäœã®ãµã€ãºãæåæ°ã§è¿ããŸããmax_size()
ïŒãã®é¢æ°ã¯ã streambuf
ãªããžã§ã¯ãã«streambuf
ããšãã§ããæ倧æåæ°ãè¿ããŸãã
æåŸã®2ã€ã®æ©èœãé€ããŠãæ®ãã¯ããã»ã©ç°¡åã«ç解ã§ããŸããã ãŸããã»ãšãã©ã®å Žåã
streambuf
ã€ã³ã¹ã¿ã³ã¹ãåŒæ°ãšããŠéä¿¡ãã以äžã«ç€ºãããã«ãç¬ç«ããé¢æ°ãèªã¿æžãããŸãã
read_until(sock, buf, "\n");
åã®ãã©ã°ã¡ã³ãã«ç€ºããããã«ããããã¡å
šäœãç¬ç«ããé¢æ°ã«éä¿¡ããå Žåãé¢æ°ã¯ãŸããããã¡ã®ãµã€ãºãå¢ãããã©ããã確èªããå
¥åãã€ã³ã¿ãšåºåãã€ã³ã¿ãæ¢ãå¿
èŠããããŸãã ã€ãŸããèªã¿åãããŒã¿ãããã°ããããèªã¿åãããšãã§ããŸãã
äŸïŒ
read_until(sock, buf, '\n'); std::cout << &buf << std::endl;
åã®ã¹ããããã¯ããœã±ããããèªã¿åã£ãå
容ããªã»ããããŸãã 次ã®äŸã§ã¯ãäœãããã³ãããŸããã
read(sock, buf.prepare(16), transfer_exactly(16) ); std::cout << &buf << std::endl;
ãã€ãã¯èªã¿åãããŸããããã€ã³ã¿ãŒã¯ç§»åããŸããã 以äžã«ç€ºãããã«ãèªåã§ç§»åããå¿
èŠããããŸãã
read(sock, buf.prepare(16), transfer_exactly(16) ); buf.commit(16); std::cout << &buf << std::endl;
åæ§ã«ã
streambuf
ãªããžã§ã¯ãã«æžã蟌ã¿ããå Žåãããã³ç¬ç«ããæžã蟌ã¿é¢æ°ã䜿çšããå Žåã¯ã次ã®ã³ãŒããã©ã°ã¡ã³ãã䜿çšããŸãã
streambuf buf; std::ostream out(&buf); out << "hi there" << std::endl; write(sock, buf);
次ã®ã³ãŒãã¯ã
hi there
3å
hi there
ãéä¿¡ããŸãã
streambuf buf; std::ostream out(&buf); out << "hi there" << std::endl; for ( int i = 0; i < 3; ++i) write(sock, buf.data());
ããã¯ããããã¡ãç Žå£ãããããšã¯ãªããããŒã¿ã¯ããã«æ®ãããã§ãã ããŒã¿ãç Žæ£ããå Žåã¯ããããã©ã®ããã«å®è£
ãããŠãããã確èªããŠãã ããã
streambuf buf; std::ostream out(&buf); out << "hi there" << std::endl; write(sock, buf.data()); buf.consume(9);
çµè«ãšããŠã
streambuf
ã€ã³ã¹ã¿ã³ã¹å
šäœãåŠçããããšãéžæããå¿
èŠããããŸãã 埮調æŽããå Žåã¯ãåã®æ©èœã䜿çšããŸãã
èªã¿åããšæžã蟌ã¿ã«åãstreambufã€ã³ã¹ã¿ã³ã¹ã䜿çšã§ããå Žåã§ããèªã¿åãçšãšæžã蟌ã¿çšã®2ã€ã®å¥ã
ã®ã€ã³ã¹ã¿ã³ã¹ããå§ãããŸãã ããã¯ããç°¡åã«ãããæ確ã«ç¥èŠãããå€ãã®èµ·ããããééããé¿ããŸãã
streambuf
ãªããžã§ã¯ããæäœããç¬ç«ããé¢æ°
次ã®ãªã¹ãã¯ã
streambuf
ãªããžã§ã¯ããæäœããBoost.Asioã®ç¬ç«ããé¢æ°ã瀺ããŠããŸãã
read (sock, buf [, completion_function])
ïŒãã®é¢æ°ã¯ããœã±ããããstreambuf
ãªããžã§ã¯ãã«èªã¿åããŸãã æåŸã®æ©èœã¯ãªãã·ã§ã³ã§ãã ããã§ããå Žåã¯ãèªã¿åãæäœãæåãããã³ã«åŒã³åºãããæäœãå®äºãããã©ãããBoost.Asioã«éç¥ããŸãïŒå®äºããŠããªãå Žåã¯èªã¿åããç¶è¡ããŸãïŒã ãã®ã·ã°ããã£ã¯æ¬¡ã®ãšããã§ãsize_t completion(const boost::system::error_code & err, size_t bytes_transfered)
å®äºãããšãé¢æ°ã¯0ãè¿ããŸããããã¯ãèªã¿åãæäœãå®å
šã«å®äºãããã©ãããæå³ããŸãã ãŒã以å€ã®å€ãè¿ãå Žåãããã¯read_some
ã¹ããªãŒã é¢æ°ã®æ¬¡ã®åŒã³åºãã®æ倧ãã€ãæ°ãè¿ãããããšãæå³ããŸããread_at(radom_stream, offset, buf [, completion_function])
ïŒãã®é¢æ°ã¯ã©ã³ãã ã¹ããªãŒã ããèªã¿åããŸãã ããã¯ãœã±ããã«ã¯é©çšãããªãããšã«æ³šæããŠãã ããïŒã©ã³ãã ãããŒã®æŠå¿µãã¢ãã«åããŠããªãããïŒãread_until(sock, buf, char | string | regex | match_condition)
ïŒãã®é¢æ°ã¯ããã®æ¡ä»¶ãæºããããŠããéã«èªã¿åããŸãã ç¹å®ã®æåãèªã¿åãå¿
èŠãããããäžéšã®è¡ãŸãã¯æ£èŠè¡šçŸãèªã¿åãè¡ã®1ã€ãšäžèŽãããã match_condition
é¢æ°ããé¢æ°ãçµäºããå¿
èŠãããããšãéç¥ãããŸãã match_condition
é¢æ°ã®ã·ã°ããã£ã¯æ¬¡ã®ãšããã§ãmatch_conditionis pair<iterator,bool>match(iterator begin, iterator end)
; ããã§ãã¡ã€ã³ã®ã€ãã¬ãŒã¿ã¯buffers_iterator <streambuf::const_buffers_type>
ã§ãã äžèŽãããã®ãèŠã€ãã£ãå Žåããã¢ã¯æ»ããŸãïŒ passed-end-of-match
ãtrue
èšå®ããtrue
ïŒãäžèŽãããã®ãèŠã€ãããªãå Žåãä»ã®ãã¢ã¯æ»ããŸãïŒ false
èšå®ããbegin
false
ïŒãwrite(sock, buf [, completion_function])
ïŒãã®é¢æ°ã¯ããã¹ãŠã®ã³ã³ãã³ããstreambuf
ãªããžã§ã¯ãã«æžã蟌ã¿ãŸãã çµäºé¢æ°ã¯ãªãã·ã§ã³ã§ããããã®åäœã¯çµäºread()
é¢æ°ã«äŒŒãŠããŸãïŒæžã蟌ã¿æäœãå®äºãããš0ãè¿ãã次ã®write_some
ã¹ããªãŒã é¢æ°ã®åŒã³åºãäžã«æžã蟌ãŸãããã€ãæ°ã瀺ããããšãŒã以å€ã®å€ãwrite_some
ãwrite_at(random_stream,offset, buf [, completion_function])
ïŒãã®é¢æ°ã¯ã©ã³ãã ã¹ããªãŒã ã«æžã蟌ã¿ãŸãã ãã®å Žåãããœã±ããã«ã¯é©çšãããŸãããasync_read(sock, buf [, competion_function], handler)
ïŒãã®éåædoubleã®read()
é¢æ°ã ããã»ããµã®ã·ã°ããã£ã¯æ¬¡ã®ãšããã§ãvoid handler(const boost::system::error_code, size_t bytes)
ãasync_read_at(radom_stream, offset, buf [, completion_function] ,handler)
ïŒããã¯read_at()
é¢æ°ã®éåæããã«ã§ããasync_read_until (sock, buf, char | string | regex | match_condition, handler)
ïŒããã¯read_until()
é¢æ°ã®éåæããã«ã§ããasync_write(sock, buf [, completion_function] , handler)
ïŒããã¯write()
é¢æ°ã®éåæããã«ã§ããasync_write_at(random_stream,offset, buf [, completion_function], handler)
ïŒããã¯write_at()
é¢æ°ã®éåædoubleã§ãã
æ¯é³ãŸã§èªã¿ãããšããŸãããïŒ
streambuf buf; bool is_vowel(char c) { return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u'; } size_t read_complete(boost::system::error_code, size_t bytes) { const char * begin = buffer_cast<const char*>( buf.data()); if ( bytes == 0) return 1; while ( bytes > 0) { if ( is_vowel(*begin++)) return 0; else --bytes; } return 1; } ... read(sock, buf, read_complete);
ããšãã°ãæ£èŠè¡šçŸã䜿çšããå Žåãããã¯éåžžã«ç°¡åã§ãã
read_until(sock, buf, boost::regex("^[aeiou]+") );
ãŸãã¯ãäŸãå°ãå€æŽããŠã
match_condition
é¢æ°ãæ©èœãããããšãã§ããŸãã
streambuf buf; bool is_vowel(char c) { return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u'; } typedef buffers_iterator<streambuf::const_buffers_type> iterator; std::pair<iterator,bool> match_vowel(iterator b, iterator e) { while ( b != e) { if ( is_vowel(*b++)) return std::make_pair(b, true); } return std::make_pair(e, false); } ... size_t bytes = read_until(sock, buf, match_vowel);
ã³ã«ãŒãã³
2009幎ãã2010幎é ã®Boost.Asioã®äœæè
ã¯ãéåæã¢ããªã±ãŒã·ã§ã³ã®äœæãããã«å®¹æã«ããã³ã«ãŒãã³ã®éåžžã«ã¯ãŒã«ãªã¢ã€ãã¢ãå®è£
ããŸããã
ããã«ãããéåæã¢ããªã±ãŒã·ã§ã³ãç°¡åã«èšè¿°ã§ããã¢ããªã±ãŒã·ã§ã³ãé çªã«èšè¿°ãããŠãããã®ããã«ãå¶åŸ¡ãããŒãç°¡åã«ãã©ãããšãã§ããŸãã

æåã®ã±ãŒã¹ã§ã¯ãéåžžã®ã¢ãããŒãã衚瀺ãããŸãã ã³ã«ãŒãã³ã䜿çšãããšã2çªç®ã®ã±ãŒã¹ã«ã§ããã ãè¿ããªããŸãã
ç°¡åã«èšãã°ãã³ã«ãŒãã³ã䜿çšãããšãè€æ°ã®ãšã³ããªãã€ã³ãã䜿çšããŠãé¢æ°å
ã®ç¹å®ã®å Žæã§å®è¡ãäžæåæ¢ããã³åéã§ããŸãã
ã³ã«ãŒãã³ã䜿çšããå Žåã¯ã2ã€ã®ããããŒãã¡ã€ã«ãå«ããå¿
èŠããããŸãããããã®ãã¡ã€ã«ã¯ã
boost/libs/asio/example/http/server4: yield.hpp
ããã³
boost/libs/asio/example/http/server4: yield.hpp
ã®ã¿èŠã€ããããšãã§ããŸãã Boost.Asioã§ã¯ã2ã€ã®ãã¯ããš1ã€ã®ã¯ã©ã¹ãå®çŸ©ãããŠããŸãã
coroutine
ïŒãã®ã¯ã©ã¹ã¯ãããªãã®æŽŸçç©ãŸãã¯ã³ã«ãŒãã³ãå®è£
ããããã«äœ¿çšããconnection
ã¯ã©ã¹ã§ããreenter(entry)
ïŒããã¯ã³ã«ãŒãã³æ¬äœã§ãã å
¥ååŒæ°ã¯ãããšãã°ãé¢æ°å
šäœã®å
éšã§ãããã¯ãšããŠäœ¿çšããããµãã«ãŒãã³ãžã®ãã€ã³ã¿ãŒã§ãã- yieldã³ãŒãïŒã³ã«ãŒãã³ã®äžéšãšããŠåœä»€ãå®è¡ããŸãã
ããããç解ããããã«ãããã€ãã®äŸãæ€èšããŠãã ããã 第4ç« ããã¢ããªã±ãŒã·ã§ã³ãåå®è£
ããŸããããã¯ãã·ã¹ãã ã«å
¥ããå¿çããä»ã®ã©ã®ã¯ã©ã€ã¢ã³ãããã°ã«èšé²ãããŠããããéç¥ããåçŽãªã¯ã©ã€ã¢ã³ãã§ãã
ã¡ã€ã³ã³ãŒãã¯æ¬¡ã®ããã«ãªããŸãã
class talk_to_svr : public boost::enable_shared_from_this<talk_to_svr> , public coroutine, boost::noncopyable { ... void step(const error_code & err = error_code(), size_t bytes = 0) { reenter(this) { for (;;) { yield async_write(sock_, write_buffer_, MEM_FN2(step,_1,_2) ); yield async_read_until( sock_, read_buffer_,"\n", MEM_ FN2(step,_1,_2)); yield service.post( MEM_FN(on_answer_from_server)); } } } };
æåã«å€æŽãããã®ã¯ã
connect(), on_connect(), on_read(),do_read(), on_write(), do_write()
ãªã©
connect(), on_connect(), on_read(),do_read(), on_write(), do_write()
å€æ°ã®ã¡ã³ããŒé¢æ°ãæ¶å€±ãã
step()
ã
é¢æ°ã®æ¬äœã¯
reenter(this) { for (;;) { }}
ãŸãã
reenter(this)
ãæåŸã«å®è¡ããã³ãŒããšèããããšãã§ããããã次ã®ã³ãŒããåŒã³åºãããšãã§ããŸãã
reenter
ãããã¯å
ã§ã¯ãããã€ãã®é²è¡äžã®åŒã³åºãã確èªã§ããŸãã é¢æ°ãæåã«èµ·åããããšã
async_write
é¢æ°ã
async_write
ã2åç®ã¯
async_read_until
é¢æ°ã
async_read_until
ã3åç®ã¯
service.post
é¢æ°ã4åç®ã¯
async_write
ããŸãã
for(;;) {}.
ã€ã³ã¹ã¿ã³ã¹ã決ããŠå¿ããªãã§ãã ãã
for(;;) {}.
次ã®ã³ãŒããèŠãŠã¿ãŸãããã
void step(const error_code & err = error_code(), size_t bytes = 0) { reenter(this) { yield async_write(sock_, write_buffer_, MEM_FN2(step,_1,_2) ); yield async_read_until( sock_, read_buffer_, "\n",MEM_FN2(step,_1,_2)); yield service.post( MEM_FN(on_answer_from_server)); } }
åã®ã³ãŒããã©ã°ã¡ã³ãã3å䜿çšããå Žåãé¢æ°ãå
¥åããŠ
service.post
ãå®è¡ããŸãã 4åç®ã¯ã
service.post
ãæž¡ããäœãããŸããã åãããšãã5åç®ãšæ¬¡ã®ãã¹ãŠã®å Žåã«çºçããŸãã
class talk_to_svr : public boost::enable_shared_from_this<talk_to_svr> , public coroutine, boost::noncopyable { talk_to_svr(const std::string & username) : ... {} void start(ip::tcp::endpoint ep) { sock_.async_connect(ep, MEM_FN2(step,_1,0) ); } static ptr start(ip::tcp::endpoint ep, const std::string & username) { ptr new_(new talk_to_svr(username)); new_->start(ep); return new_; } void step(const error_code & err = error_code(), size_t bytes = 0) { reenter(this) { for (;;) { if ( !started_) { started_ = true; std::ostream out(&write_buf_); out << "login " << username_ << "\n"; } yield async_write(sock_, write_buf_, MEM_FN2(step,_1,_2) ); yield async_read_until( sock_,read_buf_,"\n", MEM_FN2(step,_1,_2)); yield service.post( MEM_FN(on_answer_from_server)); } } } void on_answer_from_server() { std::istream in(&read_buf_); std::string word; in >> word; if ( word == "login") on_login(); else if ( word == "ping") on_ping(); else if ( word == "clients") on_clients(); read_buf_.consume( read_buf_.size()); if (write_buf_.size() > 0) service.post( MEM_FN2(step,error_code(),0)); } ... private: ip::tcp::socket sock_; streambuf read_buf_, write_buf_; bool started_; std::string username_; deadline_timer timer_; };
æ¥ç¶ãéå§ãããšããµãŒããŒã«éåæã§æ¥ç¶ãã
start()
é¢æ°ãåŒã³åºãããŸãã æ¥ç¶ã確ç«ããããšãåããŠ
step()
å
¥ããŸãã ããã¯ããŠãŒã¶ãŒåã§ã¡ãã»ãŒãžãéä¿¡ãããšãã§ãã
ãã®åŸã
async_write
ã䜿çšããŠãã
async_write
ã䜿çšããŠã¡ãã»ãŒãžãåŠçããŸãïŒ
on_answer_from_server
ïŒã
on_answer_from_server
é¢æ°
on_answer_from_server
ã¯
on_answer_from_server
çä¿¡ã¡ãã»ãŒãžãåŠçããŸãã æåã®åèªãèªã¿ã察å¿ããé¢æ°ã«éä¿¡ããã¡ãã»ãŒãžã®æ®ããç¡èŠããŸãïŒãããã«ããŠãïŒïŒ
class talk_to_svr : ... { ... void on_login() { do_ask_clients(); } void on_ping() { std::istream in(&read_buf_); std::string answer; in >> answer; if ( answer == "client_list_changed") do_ask_clients(); else postpone_ping(); } void on_clients() { std::ostringstream clients; clients << &read_buf_; std::cout << username_ << ", new client list:" << clients. str(); postpone_ping(); } void do_ping() { std::ostream out(&write_buf_); out << "ping\n"; service.post( MEM_FN2(step,error_code(),0)); } void postpone_ping() { timer_.expires_from_now(boost::posix_time::millisec(rand() % 7000)); timer_.async_wait( MEM_FN(do_ping)); } void do_ask_clients() { std::ostream out(&write_buf_); out << "ask_clients\n"; } };
ã©ã³ãã ãªç¬éã«ãµãŒããŒãšã®æ¥ç¶ã確èªããå¿
èŠãããããããã®äŸã¯ããå°ãè€éã§ãã ãããè¡ãã«ã¯ãåããŠé¡§å®¢ãªã¹ããæ£åžžã«èŠæ±ããåŸãpingæäœã延æããŸãã 次ã«ããµãŒããŒããã®åpingã«å¯ŸããŠãå¥ã®pingæäœã延æããŸãã
ããããã¹ãŠå®è¡ããã«ã¯ã次ã®ã³ãŒãã¹ããããã䜿çšããŸãã
int main(int argc, char* argv[]) { ip::tcp::endpoint ep( ip::address::from_string("127.0.0.1"), 8001); talk_to_svr::start(ep, "John"); service.run(); }
ã³ã«ãŒãã³ã䜿çšããŠãã³ãŒãã15è¡ã«æžãããããã«èªã¿ãããããŸããã ããã§ã¯ãã³ã«ãŒãã³ã®ãããã¯ã«ã€ããŠã¯ã»ãšãã©è§ŠããŸããã§ããã ãã®åé¡ã®è©³çŽ°ã«ã€ããŠã¯ããã®
ããŒãžã«ã¢ã¯ã»ã¹ããŠ
ãã ãã ã
ãŸãšã
Boost.AsioãSTLã¹ããªãŒã ãšstreambufãªããžã§ã¯ããã©ã®ããã«ç°¡åã«äœ¿çšã§ããããèŠãŸããã ãŸããã³ã«ãŒãã³ã«ãã£ãŠã³ãŒããããã³ã³ãã¯ãã«ãªããç解ã容æã«ãªãããšã確èªããŸããã
次ã®ç« ã§ã¯ãAsio vs. Boost.Asioãããã°ã¬ãã·ããããã°ãSSLãããã³ãã®ä»ã®ãã©ãããã©ãŒã åºæã®æ©èœãªã©ã®ãããã¯ãæ±ããŸãã
ãã®èšäºã®ãªãœãŒã¹ïŒ
ãªã³ã¯ãæž
èŽããããšãããããŸãããããã«äŒããŸãããïŒ