Boost.asio C + + Network programming Translator (18)

Source: Internet
Author: User

synchronizing the service sideThe synchronization service side is also fairly straightforward. It requires two threads and one is responsible for receiving the new client. The other one is responsible for dealing with the existing client.

It cannot use a single thread; A new client is a blocking operation, so we need another thread to handle the existing client. Normally, the server is more difficult to implement than the client. On the one hand, it manages all the connected client. Since we are in sync, we need at least two threads. One accepts a new client connection (because the accept () is blocked) and there is a client that is responsible for replying to the existing.

   void Accept_thread () {       ip::tcp::acceptor acceptor (service,
                                  Ip::tcp::endpoint (Ip::tcp::v4 (),
   8001));       while (true) {
           Client_ptr New_ (new talk_to_client);           Acceptor.accept (New_->sock ());           Boost::recursive_mutex::scoped_lock LK (CS);           Clients.push_back (New_);

} }

   void Handle_clients_thread () {while       (true) {
           Boost::this_thread::sleep (Millisec (1));           Boost::recursive_mutex::scoped_lock LK (CS);           for (Array::iterator B = Clients.begin (), E = Clients.end (); b

! = e; ++B)

               (*b)->answer_to_client ();           Delete the client clients.erase that has timed out           (std::remove_if (Clients.begin (), Clients.end (),
                      Boost::bind (&talk_to_client::timed_out,_1)),
   Clients.end ());       }
   }   int main (int argc, char* argv[]) {
       Boost::thread_group Threads;       Threads.create_thread (accept_thread);       Threads.create_thread (handle_clients_thread);       Threads.join_all ();

}

in order to handle requests sent by the client separately, we need to keep a list of the client. each talk_to_client instance has a Socket,socket class that does not support copy construction, so suppose you want to save them in a std::vector method, you need a smart pointer to it. There are two ways to do this: Save a smart pointer to the socket inside talk_to_client and then create an array of talk_to_client instances, or let the talk_to_client instance save the socket in a variable way, Then create an array that points to the Talk_to_client smart pointer. I choose the latter. But you can also choose the previous way:
typedef boost::shared_ptr<talk_to_client> CLIENT_PTR;   typedef std::vector<client_ptr> Array;   Array clients;   Boost::recursive_mutex CS; Access the client array in a thread-safe manner
The main code for Talk_to_client is as follows:
struct talk_to_client:boost::enable_shared_from_this<talk_to_client>   {
       Talk_to_client () {...}       std::string username () const {return username_;}       void Answer_to_client () {
           try {               read_request ();
               Process_request ();           } catch (boost::system::system_error&) {

Stop (); }

           if (Timed_out ())               stop ();
       }       void Set_clients_changed () {clients_changed_ = true;}       Ip::tcp::socket & Sock () {return sock_;}       BOOL Timed_out () const {
           Ptime now = Microsec_clock::local_time ();           Long Long ms = (now-last_ping). Total_milliseconds ();           return MS > 5000;
       }       void Stop () {
           Boost::system::error_code err; Sock_.close (err);       }
void Read_request () {
           if (sock_.available ())

Read_)); }

... private:

Already_read_ + = Sock_.read_some (    buffer (buff_ + already_read_, Max_msg-already_
       // ...  Same as in synchronous Client       bool clients_changed_;       Ptime last_ping;

};

The code above has a very good self-interpretation. The most important method is Read_request ().

It is only readable if there is valid data, and the service will never clog:

void Process_request () {       bool Found_enter = Std::find (buff_, buff_ + already_read_, ' \ n ')
                           < buff_ + Already_read_;
       if (!found_enter)           return;//message isn't full
       Process the msg       last_ping = Microsec_clock::local_time ();       size_t pos = Std::find (buff_, buff_ + already_read_, ' \ n ')-
   buff_;       std::string msg (buff_, POS);       Std::copy (buff_ + already_read_, buff_ + max_msg, buff_);       Already_read_-= pos + 1;
       if (Msg.find ("login") = = 0) on_login (msg);       else if (Msg.find ("ping") = = 0) on_ping ();       else if (Msg.find ("ask_clients") = = 0) on_clients ();       else std::cerr << "Invalid msg" << msg << Std::endl;
   }   void On_login (const std::string & msg) {
       Std::istringstream in (msg);       In >> username_ >> username_;       Write ("Login ok\n");       Update_clients_changed ();

}

void On_ping () {

       Write (clients_changed_? "Ping client_list_changed\n": "Ping
   Ok\n ");       Clients_changed_ = false;
   }   void On_clients () {
       std::string msg;       {Boost::recursive_mutex::scoped_lock lk (CS);
           for (Array::const_iterator B = Clients.begin (), E = clients.   End ();
                b! = e; ++B)           msg + = (*b)->username () + "";

}

       Write ("clients" + msg + "\ n");   }
   void Write (const std::string & msg) {sock_.write_some (buffer (msg));}
observe Process_request (). When we read enough valid data, we need to know if we have read the entire message (assuming Found_enter is true). do so. We can avoid the possibility of reading multiple messages at once (' \ n ' messages are saved in the buffer). We then parse the entire message that was read. The rest of the code is understandable.







Boost.asio C + + Network programming Translator (18)

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.