ã¿ãªããããã«ã¡ã¯ïŒ
John Torjoã®æ¬Boost.Asio C ++ Network Programmingã®ç¿»èš³ãç¶ããŠããŸãã 第2ç« ã®ãã®éšåã§ã¯ãéåæããã°ã©ãã³ã°ã«ã€ããŠèª¬æããŸãã
å
容ïŒ
ãã®ã»ã¯ã·ã§ã³ã§ã¯ãéåæããã°ã©ãã³ã°ã§äœæ¥ãããšãã«çºçããåé¡ã®ããã€ãã«ã€ããŠè©³ãã説æããŸãã äžåºŠèªãã åŸããããã®æŠå¿µã®çè§£ãæ·±ããããã«ããã®æ¬ãèªã¿é²ããªãããããã«æ»ãããšããå§ãããŸãã
éåæã§äœæ¥ããå¿
èŠæ§
åè¿°ããããã«ãååãšããŠãåæããã°ã©ãã³ã°ã¯éåæããã°ã©ãã³ã°ãããã¯ããã«ç°¡åã§ãã ç·åœ¢ã«èããã®ãã¯ããã«ç°¡åãªã®ã§ïŒé¢æ°AãåŒã³åºããçµäºåŸã«ãã³ãã©ãŒãåŒã³åºãã颿°BãåŒã³åºããçµäºåŸã«ãã³ãã©ãŒãåŒã³åºãããªã©ãã€ãã³ããã³ãã©ãŒã®ããã«èããããšãã§ããŸãïŒã åŸè
ã®å Žåãããšãã°ã5ã€ã®ã€ãã³ããå®è¡ã§ããŸãããå®è¡ãããé åºãèŠã€ããããšã¯ã§ããŸããããŸãããããããã¹ãŠæºãããããã©ãããããããŸããã
ããããéåæããã°ã©ãã³ã°ã¯ããè€éã§ãããããšãã°ã倿°ã®ã¯ã©ã€ã¢ã³ããåæã«åŠçããå¿
èŠããããµãŒããŒãäœæããå Žåã¯ãããããããã奜ãã§ãããã ã¯ã©ã€ã¢ã³ããå€ãã»ã©ãéåæããã°ã©ãã³ã°ã¯åæããã°ã©ãã³ã°ã«æ¯ã¹ãŠç°¡åã«ãªããŸãã
1000ã®ã¯ã©ã€ã¢ã³ããåæã«åŠçããã¢ããªã±ãŒã·ã§ã³ããããã¯ã©ã€ã¢ã³ããããµãŒããŒãžã®ãããã³ãµãŒããŒããã¯ã©ã€ã¢ã³ããžã®åã¡ãã»ãŒãžãæåã\ nãã§çµãããšããŸãã
åæã³ãŒãã1ã¹ã¬ããïŒ
using namespace boost::asio; struct client { ip::tcp::socket sock; char buff[1024];
ãµãŒããŒïŒããã³åºæ¬çã«ã¯ãã¹ãŠã®ãããã¯ãŒã¯ã¢ããªã±ãŒã·ã§ã³ïŒãäœæãããšãã«é¿ãããããšã®1ã€ã¯ãã³ãŒããå¿çã忢ããããšã§ãã ãã®å Žåã
handle_clients()
颿°ãã§ããã ããããã¯ããªãããã«ããŸãã æ©èœãããããã®æç¹ã§ãããã¯ãããŠããå Žåãã¯ã©ã€ã¢ã³ãããã®ãã¹ãŠã®çä¿¡ã¡ãã»ãŒãžã¯ãæ©èœãããã¯è§£é€ããããŸã§åŸ
æ©ããåŠçãéå§ããŸãã
å¿çæ§ãç¶æããããã«ãããŒã¿ããã
if ( clients[i].sock.available() ) on_read(clients[i])
ã
if ( clients[i].sock.available() ) on_read(clients[i])
å Žåã«ã®ã¿ãœã±ããããèªã¿åã
if ( clients[i].sock.available() ) on_read(clients[i])
ã on_readã§ã¯ãå©çšå¯èœãªç¯å²ã§ã®ã¿èªã¿åããŸãã
read_until(c.sock, buffer(...),'\n')
ãåŒã³åºãããšã¯ãç¹å®ã®ã¯ã©ã€ã¢ã³ãããæåŸãŸã§ã¡ãã»ãŒãžãèªã¿åããŸã§ãããã¯ããããããè¯ãã¢ã€ãã¢ã§ã¯ãããŸããïŒããããã€èµ·ãããããããŸããïŒ ã
ããã§ã®ããã«ããã¯ã¯
on_read_msg()
颿°ã§ãã ãã®é¢æ°ãå®è¡ããããŸã§ããã¹ãŠã®çä¿¡ã¡ãã»ãŒãžã¯äžæåæ¢ãããŸãã ããŸãæžããã颿°
on_read_msg()
ã¯ãããèµ·ãããªãããšãä¿èšŒããŸãããèµ·ããå¯èœæ§ããããŸãïŒäŸãã°ããããã¡ããã£ã±ãã®å Žåããœã±ãããžã®æžã蟌ã¿ããããã¯ãããããšããããŸãïŒã
åæã³ãŒãã10ã¹ã¬ããïŒ
using namespace boost::asio; struct client {
è€æ°ã®ã¹ã¬ããã䜿çšããã«ã¯ãããããåæããå¿
èŠããããŸããããã¯
set_reading
ïŒïŒããã³
set_unreading()
颿°ãè¡ãããšã§ãã
set_reading()
颿°ã¯éåžžã«éèŠã§ãã ãèªãããšãã§ããèªãããšãã§ãããã©ããã確èªãããããšã¯ã1ã€ã®ã¹ãããã§è¡ãããŸãã 2ã€ã®ã¹ãããïŒãèªã¿åãå¯èœãã©ããã確èªããããšãèªã¿åããéå§ãããïŒã§è¡ãå Žåã2ã€ã®ã¹ã¬ãããéå§ã§ããŸãã1ã€ã¯ã¯ã©ã€ã¢ã³ãã®èªã¿åãã確èªãããã1ã€ã¯åãã¯ã©ã€ã¢ã³ãã®
on_read
颿°ãåŒã³åºããŸããé·ãç®ã§èŠãã°ãããã¯ããŒã¿ã®ç Žæã«ã€ãªãããå Žåã«ãã£ãŠã¯ã·ã¹ãã ã®ã¯ã©ãã·ã¥ã«ããã€ãªãããŸãã
ã³ãŒããããè€éã«ãªã£ãŠããããšã«æ°ä»ãã§ãããã
3çªç®ã®ãªãã·ã§ã³ã¯ãåæã³ãŒããã€ãŸãã¯ã©ã€ã¢ã³ãããšã«1ã€ã®ã¹ã¬ãããæã€ããšãå¯èœã§ãã ããããåæé¡§å®¢ã®æ°ãå¢ãããšãããã¯äž»ã«èš±å®¹ã§ããªãæäœã«ãªããŸãã
次ã«ãéåæãªãã·ã§ã³ã«ã€ããŠæ€èšããŸãã ç§ãã¡ã¯åžžã«éåæã®èªã¿åãæäœãè¡ããŸããã ã¯ã©ã€ã¢ã³ããèŠæ±ãè¡ããšã
on_read
æäœã
on_read
ãå¿çããæ¬¡ã®èŠæ±ãå°çãããŸã§åŸ
æ©ããŸãïŒå¥ã®éåæèªã¿åãæäœãéå§ããŸãïŒã
éåæã³ãŒãã10ã¹ã¬ããïŒ
using namespace boost::asio; io_service service; struct client { ip::tcp::socket sock; streambuf buff;
ã³ãŒããã©ãã»ã©ç°¡åã«ãªã£ããã«æ³šç®ããŠãã ããã
client
æ§é ã«ã¯2ã€ã®ã¡ã³ããŒãããããŸãã
async_read_until
handle_clients()
ã¯
async_read_until
åŒã³åºã
async_read_until
ã10åã®ã¹ã¬ãããäœæããããããã
service.run()
ãåŒã³åºããŸãã ãããã®ã¹ã¬ããã¯ãã¯ã©ã€ã¢ã³ããžã®ãã¹ãŠã®éåæèªã¿åããŸãã¯æžãèŸŒã¿æäœãåŠçããŸãã æ³šæãã¹ããã1ã€ã®ç¹ã¯ã
on_read()
颿°ãåžžã«æ¬¡ã®éåæèªã¿åãæäœã®æºåãããããšã§ãïŒæåŸã®è¡ãåç
§ïŒã
éåæé¢æ°runïŒïŒãrun_oneïŒïŒãpollïŒïŒãpoll_oneïŒïŒ
ãªã¹ãã³ã°ã«ãŒããå®è£
ããããã«ã
io_service
ã¯ã©ã¹ã¯
run(), run_one(), poll()
ããã³
poll_one()
ãªã©ã®4ã€ã®é¢æ°ãæäŸããŸãã ã»ãšãã©ã®å Žåã
service.run()
äœæ¥ããŸãã ããã§ã¯ãä»ã®æ©èœã䜿çšããŠéæã§ããããšãåŠç¿ããŸãã
çµ¶ããåã
ç¹°ãè¿ã
run()
ãä¿çäžã®æäœãå®äºãããããŠãŒã¶ãŒã
io_service::stop()
åŒã³åºããŸã§ã
run()
ã¯æ©èœããŸãã
io_service
ã€ã³ã¹ã¿ã³ã¹ãæ©èœããç¶ããã«ã¯ãéåžžã1ã€ä»¥äžã®éåææäœã远å ããããããçµäºããããæ¬¡ã®ã³ãŒãã«ç€ºãããã«è¿œå ãç¶ããŸãã
using namespace boost::asio; io_service service; ip::tcp::socket sock(service); char buff_read[1024], buff_write[1024] = "ok"; void on_read(const boost::system::error_code &err, std::size_t bytes) ; void on_write(const boost::system::error_code &err, std::size_t bytes) { sock.async_read_some(buffer(buff_read), on_read); } void on_read(const boost::system::error_code &err, std::size_t bytes) {
service.run()
ãåŒã³åºããããšãå°ãªããšã1ã€ã®éåææäœãåŸ
æ©ããŠããŸãã ãœã±ããããµãŒããŒã«æ¥ç¶ãããšã
on_connect
ã
on_connect
ãå¥ã®éåææäœã远å ãããŸãã
on_connect
ã®çµäºåŸããŸã ã¹ã±ãžã¥ãŒã«ãããæäœã1ã€ãããŸãïŒ
read
ïŒã
on_read
æäœã
on_read
ãšãå¿çãæžã蟌ã¿ããã1ã€ã®ã¹ã±ãžã¥ãŒã«ãããæäœïŒ
write
ïŒã远å ãããŸãã
on_write
颿°ã
on_write
ããµãŒããŒããæ¬¡ã®ã¡ãã»ãŒãžãèªã¿åã
on_write
ãå¥ã®ã¹ã±ãžã¥ãŒã«ãããæäœã远å ãããŸãã
on_write
颿°ã
on_write
ã1ã€ã®ã¹ã±ãžã¥ãŒã«ãããæäœïŒ
read
ïŒããããŸãã ãã®ãããã¢ããªã±ãŒã·ã§ã³ãéããããšã決å®ãããŸã§ããã®ãµã€ã¯ã«ãç¶ããŸãã
颿°run_oneïŒïŒãpollïŒïŒãpoll_oneïŒïŒ
éåæé¢æ°ãã³ãã©ãŒã¯ã
io_service::run
ãåŒã³åºãããã¹ã¬ãããšåãã¹ã¬ããã§åŒã³åºãããããšã«æ³šæããŠ
io_service::run
ã 䜿çšããæ©èœã¯å°ãªããšã90ã95ïŒ
ã§ãããããç°¡åã«ããããã«ãããæ³šç®ãããŠããŸãã ã¹ããªãŒã å
ã®
run_one(), poll()
ããŸãã¯
poll_one()
åŒã³åºãã«ã€ããŠãåæ§ã§ãã
run_one()
颿°ã¯ãè€æ°ã®éåææäœãå®è¡ããŠéä¿¡ããŸãã
- ã¹ã±ãžã¥ãŒã«ãããæäœããªãå Žåã颿°ã¯ããã«çµäºãã0ãè¿ããŸã
- ä¿çäžã®æäœãããå Žåãæåã®æäœã®æ©èœãããã¯ãå®è¡ããã1ãè¿ãããŸã
次ã®åçã®ã³ãŒããæ€èšã§ããŸãã
io_service service; service.run();
run_once()
ã䜿çšããŠéåææäœãéå§ãããããå®äºããã®ãåŸ
ã€ããšãã§ããŸãã
io_service service; bool write_complete = false; void on_write(const boost::system::error_code & err, size_t bytes) { write_complete = true; } ... std::string data = "login ok"; write_complete = false; async_write(sock, buffer(data), on_write); do service.run_once() while (!write_complete);
ãŸãã
blocking_tcp_client.cpp
ã
blocking_udp_client.cpp
ãªã©ãBoost.Asioã«ãã³ãã«ãããŠãã
run_one()
ã䜿çšããäŸããããŸãã
poll_one
颿°ã¯ããããã¯ããã«å®è¡ããæºåãã§ããŠããä¿çäžã®æäœã1ã€ã ãèµ·åããŸãã
- ãããã¯ããã«éå§ããæºåãã§ããŠããä¿çäžã®æäœãå°ãªããšã1ã€ããå Žåã
run_one()
ã¯ãããéå§ããŠ1ãè¿ããŸãã - ãã以å€ã®å Žåã颿°ã¯ããã«çµäºãã0ãè¿ããŸãã
ãããã¯ããã«éå§ããæºåãã§ããŠããä¿çäžã®æäœã¯ãé垞次ã®ããããã§ãã
- æéåãã«ãªã£ãŠããã
async_wait
ãã³ãã©ãŒã«ãã£ãŠåŒã³åºãããå¿
èŠãããã¿ã€ã㌠- å®äºããI / OæäœïŒããšãã°
async_read
ïŒãšãã®ãã³ãã©ãŒãasync_read
å¿
èŠããããŸã - 以åã«
io_services
ã€ã³ã¹ã¿ã³ã¹io_services
远å ãããã«ã¹ã¿ã ãã³ãã©ãŒïŒããã«ã€ããŠã¯ã次ã®ã»ã¯ã·ã§ã³ã§è©³ãã説æããŸãïŒ
poll_one
ã䜿çšããŠãå®äºããI / Oæäœã®ãã¹ãŠã®ãã³ãã©ãŒãå®è¡ãããŠããããšã確èªããæ¬¡ã®ã¿ã¹ã¯ã«é²ãããšãã§ããŸãã
io_service service; while ( true) {
poll()
颿°ã¯ãä¿çäžã®ãã¹ãŠã®æäœãå®è¡ãããããã¯ããã«å®è¡ã§ããŸãã æ¬¡ã®ã³ãŒãã¯åçã§ãã
io_service service; service.poll();
以åã®ãã¹ãŠã®é¢æ°ã¯ã倱æããå Žåã«
boost::system::system_error
ãã¹ããŒããŸãã ããããããã¯æ±ºããŠèµ·ãããªãã¯ãã§ãã ããã§ã¹ããŒããããšã©ãŒã¯éåžžã¯ã©ãã·ã¥ã«ã€ãªãããŸãããªãœãŒã¹ãšã©ãŒãããã³ãã©ãŒã®1ã€ãäŸå€ãã¹ããŒããå¯èœæ§ããããŸãã ãããã®å Žåã§ããå颿°ã«ã¯äŸå€ãã¹ããŒããªããªãŒããŒããŒãããããŸããã
boost::system::error_code
ãåŒæ°ãšããŠ
boost::system::error_code
ããããæ»ãå€ãšããŠèšå®ããŸãã
io_service service; boost::system::error_code err = 0; service.run(err); if ( err) std::cout << "Error " << err << std::endl;
éåææäœ
éåææäœãšã¯ããµãŒããŒã«æ¥ç¶ããŠããã¯ã©ã€ã¢ã³ãã®éåæåŠçããœã±ããããã®éåæã®èªã¿åãããã³æžã蟌ã¿ã ãã§ã¯ãããŸããã ããã¯ãéåæã§å®è¡ãããå¯èœæ§ã®ãããã¹ãŠã®æäœã察象ãšããŠããŸãã
ããã©ã«ãã§ã¯ããã¹ãŠã®éåæé¢æ°ã®ãã³ãã©ãŒãåŒã³åºãããé åºã¯ããããŸããã ããã«ãéåžžãæ¬¡ã®åŒã³åºãã¯éåæã§ãïŒéåæã®èªã¿åã/æžã蟌ã¿/åä¿¡ãœã±ããããçºä¿¡ïŒã
service.post()
ã䜿çšããŠãéåæã«åŒã³åºãããã«ã¹ã¿ã 颿°ã远å ã§ããŸããæ¬¡ã«äŸã瀺ããŸãã
#include <boost/thread.hpp> #include <boost/bind.hpp> #include <boost/asio.hpp> #include <iostream> using namespace boost::asio; io_service service; void func(int i) { std::cout << "func called, i= " << i << std::endl; } void worker_thread() { service.run(); } int main(int argc, char* argv[]) { for ( int i = 0; i < 10; ++i) service.post(boost::bind(func, i)); boost::thread_group threads; for ( int i = 0; i < 3; ++i) threads.create_thread(worker_thread); // wait for all threads to be created boost::this_thread::sleep( boost::posix_time::millisec(500)); threads.join_all(); }
åã®äŸã§ã¯ã
service.post(some_function)
ã¯éåæé¢æ°åŒã³åºãã远å ããŸãã ãã®é¢æ°ã¯ã
io_service
ã€ã³ã¹ã¿ã³ã¹ã«
service.run()
ãåŒã³åºãã¹ã¬ããã®1ã€ã§ãã®
some_function
ãåŒã³åºãããã«èŠæ±ãããšããã«çµäºããŸãã ãã®äŸã§ã¯ã3ã€ã®ã¹ã¬ããã®ãããããäºåã«äœæããŸããã éåæé¢æ°ãã©ã®é åºã§åŒã³åºããããã確èªããããšã¯ã§ããŸããã 远å ãããé ã«åŒã³åºãããããšãæåŸ
ããªãã§ãã ããïŒ
post()
ïŒã åã®äŸã®çµæã¯æ¬¡ã®ãšããã§ãã
func called, i= 0 func called, i= 2 func called, i= 1 func called, i= 4 func called, i= 3 func called, i= 6 func called, i= 7 func called, i= 8 func called, i= 5 func called, i= 9
éåæé¢æ°ã«ãã³ãã©ãŒãå²ãåœãŠããå ŽåããããŸãã ããšãã°ãã¬ã¹ãã©ã³ïŒ
go_to_restaurant
ïŒã«è¡ãã
order
ãé£ã¹ãªããã°ãªããªãïŒ
go_to_restaurant
ïŒãšããŸãããã æåã«ã¬ã¹ãã©ã³ã«æ¥ãŠã泚æããŠããé£ã¹ããã ãã§ãã ãããè¡ãã«ã¯ã
io_service::strand
ã䜿çšããŠãåŒã³åºãéåæãã³ãã©ãŒãå²ãåœãŠãŸãã æ¬¡ã®äŸãèããŠã¿ãŸãããã
using namespace boost::asio; io_service service; void func(int i) { std::cout << "func called, i= " << i << "/" << boost::this_thread::get_id() << std::endl; } void worker_thread() { service.run(); } int main(int argc, char* argv[]) { io_service::strand strand_one(service), strand_two(service); for ( int i = 0; i < 5; ++i) service.post( strand_one.wrap( boost::bind(func, i))); for ( int i = 5; i < 10; ++i) service.post( strand_two.wrap( boost::bind(func, i))); boost::thread_group threads; for ( int i = 0; i < 3; ++i) threads.create_thread(worker_thread);
äžèšã®ã³ãŒãã§ã¯ãæåã®5ã€ã®ã¹ããªãŒã IDãšæåŸã®5ã€ã®ã¹ããªãŒã IDãé çªã«è¡šç€ºãããŸããã€ãŸãã
func called, i = 0
ããå
func called, i = 0
ã衚瀺ã
func called, i = 1
func called, i = 2
ããŸãã ã åãããšã
func called, i = 5
ãã
func called, i = 5
func called, i = 6
ããã³
func called, i = 6
ã
func called, i = 7
ãªããŸãã 颿°ãã·ãŒã±ã³ã·ã£ã«ã«åŒã³åºããããšããŠããããã¯ãããããã¹ãŠåãã¹ã¬ããã§åŒã³åºãããããšãæå³ããªãããšã«æ³šæããŠãã ããã ãã®ããã°ã©ã ã®å¯èœãªå®è£
ã¯æ¬¡ã®ãšããã§ãã
func called, i= 0/002A60C8 func called, i= 5/002A6138 func called, i= 6/002A6530 func called, i= 1/002A6138 func called, i= 7/002A6530 func called, i= 2/002A6138 func called, i= 8/002A6530 func called, i= 3/002A6138 func called, i= 9/002A6530 func called, i= 4/002A6138
éåæãã¹ãïŒïŒvsãã£ã¹ãããïŒïŒvsã©ããïŒïŒ
Boost.Asioã¯ãéåæåŒã³åºãã«é¢æ°ãã³ãã©ãŒã远å ãã3ã€ã®æ¹æ³ãæäŸããŸãã
service.post(handler)
ïŒãã®é¢æ°ã¯ãæå®ããããã³ãã©ãŒãåŒã³åºãããã«io_service
ã€ã³ã¹ã¿ã³ã¹ã«èŠæ±ãè¡ã£ãçŽåŸã«io_service
ããããã«ããŸãã ãã³ãã©ãŒã¯ãåŸã§service.run()
ãåŒã³åºããã¹ã¬ããã®1ã€ã§åŒã³åºãããŸããservice.dispatch(handler)
ïŒããã¯ãæå®ããããã³ãã©ãŒãåŒã³åºãio_service
ã€ã³ã¹ã¿ã³ã¹ãžã®èŠæ±ã§ãããããã«ãçŸåšã®ã¹ã¬ãããservice.run()
ãåŒã³åºããå Žåã颿°å
ã®ãã³ãã©ãŒãåŒã³åºãããšãã§ããŸããservice.wrap(handler)
ïŒãã®é¢æ°ã¯ã service.dispatch(handler)
ãåŒã³åºãã©ãããŒé¢æ°ãäœæããŸãã ããã¯å°ããããã«ããã§ãããããã«ãã®æå³ã説æããŸãã
åã®ã»ã¯ã·ã§ã³ã§
service.post()
ã䜿çšããäŸãšãããã°ã©ã å®è¡ã®å¯èœãªçµæãââèŠãŸããã 倿ŽããŠã
service.dispatch
ãçµæã«ã©ã®ããã«åœ±é¿ãããã確èªããŸãã
using namespace boost::asio; io_service service; void func(int i) { std::cout << "func called, i= " << i << std::endl; } void run_dispatch_and_post() { for ( int i = 0; i < 10; i += 2) { service.dispatch(boost::bind(func, i)); service.post(boost::bind(func, i + 1)); } } int main(int argc, char* argv[]) { service.post(run_dispatch_and_post); service.run(); }
ããã§äœãèµ·ãã£ãŠãããã説æããåã«ãããã°ã©ã ãå®è¡ããŠçµæãèŠãŠã¿ãŸãããã
func called, i= 0 func called, i= 2 func called, i= 4 func called, i= 6 func called, i= 8 func called, i= 1 func called, i= 3 func called, i= 5 func called, i= 7 func called, i= 9
æåã«å¶æ°ãæžã蟌ãŸããæ¬¡ã«å¥æ°ãæžã蟌ãŸããŸãã ããã¯ã
dispatch()
ã䜿çšããŠå¶æ°ãæžã蟌ã¿ã
post()
ã䜿çšããŠå¥æ°ãæžã蟌ãããã§ãã çŸåšã®ã¹ã¬ããã
service.run()
dispatch()
ãåŒã³åºããŠããããã
dispatch()
ã¯çµäºããåã«ãã³ãã©ãŒãåŒã³åºããŸãããpostïŒïŒã¯ããã«çµäºããŸãã
ããŠã
service.wrap(handler)
ã«ã€ããŠè©±ããŸãããã wrapïŒïŒã¯ãå¥ã®é¢æ°ã®åŒæ°ãšããŠäœ¿çšã§ãããã¡ã³ã¯ã¿ãŒãè¿ããŸãã
using namespace boost::asio; io_service service; void dispatched_func_1() { std::cout << "dispatched 1" << std::endl; } void dispatched_func_2() { std::cout << "dispatched 2" << std::endl; } void test(boost::function<void()> func) { std::cout << "test" << std::endl; service.dispatch(dispatched_func_1); func(); } void service_run() { service.run(); } int main(int argc, char* argv[]) { test( service.wrap(dispatched_func_2)); boost::thread th(service_run); boost::this_thread::sleep( boost::posix_time::millisec(500)); th.join(); }
æåå
test(service.wrap(dispatched_func_2));
dispatched_func_2
ãã©ããããåŒæ°ãšããŠ
test
ã«æž¡ããããã¡ã³ã¯ã¿ãŒãäœæããŸãã
test()
åŒã³åºããããšãåŒã³åºãã
dispatched_func_1()
ã«ãªãã€ã¬ã¯ããã
func()
ãåŒã³åºããŸãã ãã®æç¹ã§ã
func()
åŒã³åºã
func()
service.dispatch(dispatched_func_2)
func()
åçã§ããããšãããããŸãããããã¯é çªã«åŒã³åºãããããã§ãã ããã°ã©ã åºåã¯ããã確èªããŸãïŒ
test dispatched 1 dispatched 2
io_service::strand
ã¯ã©ã¹ïŒéåæã¢ã¯ã·ã§ã³ã®ã·ãªã¢ã«åã«äœ¿çšïŒã«ã¯ã颿°
poll(), dispatch()
wrap()
ãå«ãŸããŠããŸãã ãããã®æå³ã¯ã
io_service
ã®
poll(), dispatch()
ããã³
wrap()
io_service
ã®æå³ãšåã
io_service
ã ãã ããã»ãšãã©ã®å Žåã
io_service::strand::wrap()
颿°ã¯
io_service::poll()
ãŸãã¯
io_service::dispatch()
åŒæ°ãšããŠã®ã¿äœ¿çšããŸãã
çãç¶ããããã«
æ¬¡ã®æäœãå®è¡ããŠèšããŸãã
io_service service; ip::tcp::socket sock(service); char buff[512]; ... read(sock, buffer(buff));
ãã®å Žåã
sock
ãš
buff
ã¯äž¡æ¹ãšã
read()
åŒã³åºãã§çãæ®ãã¯ãã§ãã ã€ãŸãã
read()
åŒã³åºããå®äºããåŸãæå¹ã§ãªããã°ãªããŸããã ããã¯ãŸãã«ããªããæåŸ
ãããã®ã§ãã颿°ã«æž¡ãåŒæ°ã¯ãã¹ãŠããã®äžã§æå¹ã§ãªããã°ãªããŸããã éåæã«é²ããšãäºæ
ã¯ããã«è€éã«ãªããŸãã
io_service service; ip::tcp::socket sock(service); char buff[512]; void on_read(const boost::system::error_code &, size_t) {} ... async_read(sock, buffer(buff), on_read);
ãã®å Žåã
sock
ãš
buff
ã¯
read
æäœèªäœã«èããå¿
èŠããã
read
ããéåæã§ãããããããããã€çºçãããã¯ããããŸããã
ãœã±ãããããã¡ãŒã䜿çšããå ŽåãéåæåŒã³åºãã«èãã
buffer
ã€ã³ã¹ã¿ã³ã¹ã䜿çšã§ããŸãïŒ
boost::shared_array<>
ïŒã ããã§ã¯ããœã±ãããšèªã¿åã/æžã蟌ã¿ãããã¡ãå
éšã«å«ãã¯ã©ã¹ãäœæããããšã«ãããåãååã䜿çšã§ããŸãã æ¬¡ã«ããã¹ãŠã®éåæåŒã³åºãã«å¯ŸããŠã
boost::bind
functorãå
±æãã€ã³ã¿ãŒã§æž¡ããŸãïŒ
using namespace boost::asio; io_service service; struct connection : boost::enable_shared_from_this<connection> { typedef boost::system::error_code error_code; typedef boost::shared_ptr<connection> ptr; connection() : sock_(service), started_(true) {} void start(ip::tcp::endpoint ep) { sock_.async_connect(ep, boost::bind(&connection::on_connect, shared_from_this(), _1)); } void stop() { if ( !started_) return; started_ = false; sock_.close(); } bool started() { return started_; } private: void on_connect(const error_code & err) {
ãã¹ãŠã®éåæåŒã³åºãã§ã¯ã
boost::bind
ãã¡ã³ã¯ã¿ãŒãåŒæ°ãšããŠéä¿¡ãããŸãã ãã®ãã¡ã³ã¯ã¿ãŒã¯ã
connection
ã€ã³ã¹ã¿ã³ã¹ãžã®å
±æãã€ã³ã¿ãŒãå
éšçã«ä¿åããŸãã éåææäœãä¿çãããŠããéãBoost.Asioã¯
boost::bind
functorã®ã³ããŒãä¿åããããã¯
connection
ãžã®å
±æãã€ã³ã¿ãŒãä¿åã
connection
ã åé¡ã¯è§£æ±ºããŸããïŒ
ãã¡ããã
connection
ã¯ã©ã¹ã¯åãªã
skeleton
ã¯ã©ã¹ã§ãã ããŒãºã«åãããŠèª¿æŽããå¿
èŠããããŸãïŒãµãŒããŒã®å Žåã¯ãå€èгãå®å
šã«ç°ãªããŸãïŒã æ°ããæ¥ç¶
connection::ptr(new connection)->start(ep)
ç°¡åã«äœæã§ããããšã«æ³šæããŠãã ããã ããã«ããããµãŒããŒãžã®ïŒéåæïŒæ¥ç¶ãéå§ãããŸãã æ¥ç¶ãéãããå Žåã¯ã
stop()
ãåŒã³åºããŸãã
ã€ã³ã¹ã¿ã³ã¹ãéå§ããããšïŒ
start()
ïŒãæ¥ç¶ãåŸ
æ©ããŸãã æ¥ç¶ãçºçãããšã
on_connect()
åŒã³åºãããŸãã ãšã©ãŒããªãå Žåãèªã¿åãæäœïŒ
do_read()
ïŒãåŒã³åºãããŸãã èªã¿åãæäœãå®äºãããšãã¡ãã»ãŒãžãè§£éã§ããŸãã ã»ãšãã©ã®å Žåãã¢ããªã±ãŒã·ã§ã³ã®
on_read()
ã¯ç°ãªã£ãŠèŠããŸãã ã¡ãã»ãŒãžãéä¿¡ãããšãã¯ã
do_write()
ã§è¡ãããããã«ãã¡ãã»ãŒãžããããã¡ã«ã³ããŒããŠããéä¿¡ããå¿
èŠããããŸããããã¯ããããã¡ãéåææžãèŸŒã¿æäœã«èããªããã°ãªããªãããã§ãã æåŸã®ã¡ã¢-èšé²ãããšãã¯ãæžã蟌ãéãæå®ããå¿
èŠãããããšãå¿ããªãã§ãã ãããããããªããšããããã¡å
šäœãéä¿¡ãããŸãã
ãŸãšã
ãããã¯ãŒã¯APIã¯éåžžã«åºç¯å²ã§ãã ãã®ç« ã¯ãç¬èªã®ãããã¯ãŒã¯ã¢ããªã±ãŒã·ã§ã³ãå®è£
ãããšãã«æ»ããªã³ã¯ãšããŠå®è£
ãããŸããã
Boost.Asioã¯ãšã³ããã€ã³ãã®æŠå¿µãå®è£
ããŠãããIPã¢ãã¬ã¹ãšããŒããšèããããšãã§ããŸãã æ£ç¢ºãªIPã¢ãã¬ã¹ãããããªãå Žåã¯ã
resolver
ãªããžã§ã¯ãã䜿çšããŠã1ã€ä»¥äžã®IPã¢ãã¬ã¹ã®ä»£ããã«
www.yahoo.comãªã©ã®ãã¹ãåãå«ããããšãã§ããŸãã
ãŸããã³ã¢APIã«ãããœã±ããã¯ã©ã¹ã調ã¹ãŸããã Boost.Asioã¯TCPãUDPãããã³ICMPã®å®è£
ãæäŸããŸãããèªåã®ãããã³ã«çšã«æ¡åŒµã§ããŸãããããã¯æ°åŒ±ãªäººåãã§ã¯ãããŸããã
éåæããã°ã©ãã³ã°ã¯å¿
èŠãªæªã§ãã ç¹ã«ãµãŒããŒãäœæãããšãã«ããªããããå¿
èŠãªã®ããèŠãŸããã
éåžžãservice.run()
éåæã«ãŒããäœæããã®ã«ååãªåŒã³åºãããããŸãããããã«é²ãå¿
èŠãããå Žåã¯run_one(), poll()
ããŸãã¯ã䜿çšã§ããŸãpoll_one()
ãéåæã¢ãããŒãã䜿çšããå Žåã¯ãservice.post()
ãŸãã¯ã䜿çšããã ãã§ãç¬èªã®éåæé¢æ°ã䜿çšã§ãservice.dispatch()
ãŸããæåŸã«ãéåææäœã®å
šæéïŒå®äºãŸã§ïŒã®éããœã±ãããšãããã¡ãŒïŒèªã¿åããŸãã¯æžã蟌ã¿çšïŒã®äž¡æ¹ãæå¹ã«ä¿ã€ããã«ãç¹å¥ãªäºé²æªçœ®ãè¬ããå¿
èŠããããŸããã¯ã©ã¹connection
ã¯ããæŽŸçãenabled_shared_from_this
ããã®äžã«å¿
èŠãªãã¹ãŠã®ãããã¡ãå«ã¿ãåéåæåŒã³åºãã§ãã®æäœã«å
±æãã€ã³ã¿ãæž¡ãå¿
èŠããããŸããæ¬¡ã®ç« ã¯å€ãã®å®éçãªäœæ¥ã«ãªããŸããã¯ã©ã€ã¢ã³ã/ãµãŒããŒãšã³ãŒãªã©ã®ã¢ããªã±ãŒã·ã§ã³ãå®è£
ããéã®å€ãã®ã¢ããªã±ãŒã·ã§ã³ã³ãŒãã£ã³ã°ãã¿ãªãããããããšãããããŸããïŒ