Boost.asio C + + Network programming translator (28)

Source: Internet
Author: User

co-processBoost.asio's author has implemented a very cool part of the process for 2009-2010 years, which allows you to design your asynchronous application more simply. they allow you to simultaneously enjoy the best part of both synchronous and asynchronous Worlds, which is: Asynchronous programming but very simple to follow process control, as if the application is implemented by process. The normal process has been shown in Scenario 1, and if you use the association, you will be as close as possible to scenario 2. simply put, the process allows a portal to be paused and resumed at a specified location in a method. If you want to use the co-process, you need only two header files found in the Boost/libs/asio/example/http/server4 directory: YIELD.HPP and COROUTINE.HPP. Here, Boost.asio defines two virtual keywords (macros) and a class:
    • Coroutine: This class is inherited or used by your connection class when implementing a co-process.
    • Reenter (Entry): This is the main body of the process. The parameter entry is a pointer to an Coroutine instance that is used as a block of code throughout the method.
    • Yield code: It runs a declaration as part of the Writers Association process. The next time you enter a method, the operation executes after this code.
for a better understanding, let's look at an example. We will re-implement the fourth chapter, the asynchronous client application, which is a simple to log in, Ping, and then can tell you other clients to sign in to the client app. The core code is similar to the following code snippet:
    1.   class Talk_to_svr:public boost::enable_shared_from_this<talk_to_svr>, public coroutine, Boost::non copyable { 
        
        reen ter (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));  

      }}}

      };&NBSP;

the first thing to change is that we only have a method called step (), not a large number of member methods like Connect (), On_connect (), On_read (), Do_read (), On_write (), Do_write (), and so on. the body of the method is in reenter (this) {for (;;) {}}. You can take reenter (this) as our last run code, so this time we can execute the next code. in the reenter code block, you will find several yield declarations. The first time you enter the method, the Async_write method is executed, the second Async_read_until method is executed, the third Service.post method is executed, then the fourth time Async_write method is executed, and then continues. You can never forget for (;;) {} instance. Refer to the following code snippet:
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));       }

}

If we use the above snippet for the third time, we'll go into the method and execute service.post. When we enter the method for the fourth time, we skip the service.post and don't execute anything. The same is true when the fifth time is executed, and then the loop goes on:
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_;   };
when we start the connection, start () is called and then asynchronously connects to the server. When the connection is complete, we enter step () for the first time. This is when we send our login information. after that, we use Async_write, then Async_read_until, and then process the message (on_answer_from_server). in On_answer_from_server, we process the incoming message; we read the first character and then distribute it to the appropriate method. Then, ignore the rest of the message (if there are still some messages not finished):
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::p osix_time::millisec (rand ()%
   7000));           Timer_.async_wait (MEM_FN (do_ping));
       }       void Do_ask_clients () {
           Std::ostream out (&write_buf_); Out << "ask_clients\n";       }

};

The example is a bit more complicated because we need to ping the server randomly. Implement this we need to do a ping after the client list is first requested. Then, in the result of each ping returned from the server, we do another ping operation. Use the following code snippet to run all of this process:
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 ();

}

using the co-process, we saved 15 lines of code, and the code became more readable. Here we are just touching the process. If you want to learn more, please log in to the author's profile: Http://blog.think-async. com/2010_03_01_archive.html.
Summarywe've learned how Boost.asio can play with STL stream and Streambuf objects. We also learned how the process can make our code more concise and readable. Here are the plays, such as Asio VS Boost.asio, advanced debugging, SSL and platform-related features











Boost.asio C + + Network programming translator (28)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.