asynchronous client/servernow, it's more fun (and harder) async! when looking at a chart, you need to know that Boost.asio represents an asynchronous call executed by Boost.asio. For example Do_read (), Boost.asio and On_read () represent the logical flow from Do_read () to On_read (), but you never know when the turn is On_read (), and you just know that you will eventually call it. Asynchronous Clientthings are going to get a little complicated here, but it's definitely manageable. Of course you'll also have an app that won't clog. you should already be familiar with the following code:
#define MEM_FN (x) boost::bind (&self_type::x, Shared_from_this ()) #define MEM_FN1 (x, y) Boost::bind ( &self_type::x, Shared_from_this (), y) #define MEM_FN2 (x, Y, z) boost::bind (&self_type::x, Shared_from_ This (), y,z)
Class Talk_to_svr:public boost::enable_shared_from_this<talk_to_svr> , boost::noncopyable {
typedef TALK_TO_SVR SELF_TYPE; TALK_TO_SVR (const std::string & username)
: Sock_ (Service), Started_ (True), username_ (username), Timer_ (service) {}
void Start (Ip::tcp::endpoint EP) { Sock_.async_connect (EP, MEM_FN1 (On_connect,_1));
} public:
typedef boost::system::error_code Error_code; typedef boost::shared_ptr<talk_to_svr> PTR;
Static PTR Start (Ip::tcp::endpoint EP, const std::string &username) {
PTR New_ (new Talk_to_svr (username)); New_->start (EP); return new_;
} void Stop () {
if (!started_) return; Started_ = false; Sock_.close ();
} bool Started () {return started_;} ...
Private: size_t read_complete (const Boost::system::error_code & err, size_t
bytes) { if (err) return 0;
BOOL found = Std::find (read_buffer_, Read_buffer_ + bytes, ' \ n ')
< Read_buffer_ + bytes; return found? 0:1;
}
Private: ip::tcp::socket sock_; enum {max_msg = 1024x768}; Char read_buffer_[max_msg]; Char write_buffer_[max_msg]; BOOL Started_; std::string username_; Deadline_timer Timer_;
};
you will see an additional method Deadline_timer Timer_ is used to ping the service side, and the ping operation is also random. The following is the logic of the class:
void On_connect (const Error_code & err) { if (!err) do_write ("login" + username_ + "\ n"); else stop ();
} void On_read (const Error_code & err, size_t bytes) {
if (err) stop (); if (!started ()) return; Process the MSG std::string msg (read_buffer_, bytes); if (Msg.find ("login") = = 0) on_login (); else if (Msg.find ("ping") = = 0) on_ping (msg); else if (Msg.find ("clients") = = 0) on_clients (msg);
} void On_login () {
Do_ask_clients (); }
void on_ping (const std::string & msg) { std::istringstream in (msg); Std::string answer; In >> answer >> answer;
if (answer = = "Client_list_changed") do_ask_clients ();
else postpone_ping (); }
void on_clients (const std::string & msg) { std::string clients = MSG.SUBSTR (8); Std::cout << username_ << ", New client list:" << clients; Postpone_ping ();
}
in On_read (), the first two lines of code can be said to be bonus points. In the first line, if there is an error, we stop. In the second line, if we have stopped (stopped or just stopped), we will return. Otherwise, if all is OK, we process the incoming message. The final do_* method is as follows:
void Do_ping () {do_write ("ping\n");} void Postpone_ping () {
Timer_.expires_from_now (boost::p osix_time::millisec (rand ()% 7000));
Timer_.async_wait (MEM_FN (do_ping)); }
void Do_ask_clients () {do_write ("ask_clients\n");} void On_write (const Error_code & err, size_t bytes) {do_read ();} void Do_read () {
Async_read (sock_, buffer (read_buffer_), mem_fn2 (read_complete,_1,_2), mem_fn2 (on_read,_1,_2));
} void Do_write (const std::string & msg) {
if (!started ()) return; Std::copy (Msg.begin (), Msg.end (), write_buffer_); Sock_.async_write_some (Buffer (Write_buffer_, msg.size ()),
MEM_FN2 (on_write,_1,_2));
Note that each read operation will trigger a ping operation
- When the read operation finishes, On_read () is called
- On_read () calls On_login (), on_ping (), or on_clients ()
- Each method either issues a ping or requests a list of clients
- If we request a list of clients, he will issue a ping when the read operation accepts them.
Boost.asio C + + Network programming translator (19)