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, one for receiving new clients, and the other for handling existing clients. It cannot use a single thread; A new client is a blocking operation, so we need another thread to handle the client that already exists. Normally, the server is more difficult to implement than the client. On the one hand, it wants to manage all the clients that are already connected. Because we are synchronous, we need at least two threads, one to accept the new client connection (because the accept () is blocked) and the other to reply to the existing client.
   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 save a list of clients. each talk_to_client instance has a Socket,socket class that does not support copy construction, so if 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 chose 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; Accessing 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-release. The most important method is Read_request (). It is only read if there is valid data, so the server will never block:
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 (if Found_enter is true). In doing so, we can avoid the possibility of reading multiple messages at once (' \ n ' after the message is saved in the buffer), and then we parse the entire message 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.