Code from: Boost
#include <boost/asio/deadline_timer.hpp> #include <boost/asio/io_service.hpp> #include <boost/asio/ ip/tcp.hpp> #include <boost/asio/read_until.hpp> #include <boost/asio/streambuf.hpp> #include < boost/asio/write.hpp> #include <boost/bind.hpp> #include <iostream> using Boost::asio::d eadline_timer
;
Using Boost::asio::ip::tcp;
This class manages socket timeouts by giving a deadline concept//gives some of the deadlines for asynchronous operations that they must complete.
The deadline is made by an "actor", which performs a continuous life cycle//This class manages sockets timeouts by applying the concept of a deadline.
Some asynchronous operations is given deadlines by which they must complete. Some asynchronous operations are given deadline, and they must complete their operations//deadline are enforced by the "actor" Enforcement//Client Object Model:////+----------------+//|
| // | Check_deadline |<---+//| |
| // +----------------+ | Async_wait ()//|
|
+---------+////If the "actor" determines that the deadline has expired and the socket is closed, any unfinished operations are therefore canceled. Connection is established, you need to try each port (endpoint) sequentially until there is a connectionSuccessful, or the available port (endpoint) is exhausted//if the deadline actor closes the socket, the actor responsible for the connection is woken up and switched to write a port. //
// +---------------+
// |
| // | Start_connect |<---+//| |
|
// +---------------+ | // |
| async_-| +----------------+//Connect () | |
| +--->|
Handle_connect | // |
| +----------------+//://Once the connection is successful://actor responsible for connection ://(the Connect actor)://Divided into two ways://:// An actor is used to read a message: Another actor is used to send a heartbeat//://+------------+: + + ------------+
// | |<--------+--->|
| // | Start_read | | Start_write |<---+//| |<---+ | |
| // +------------+ | +-------------+ | Async_wait ()//| | |
| async_-| +-------------+ async_-| +--------------+//read_-| | | Write () | |
| Until () +--->| Handle_read | +--->|
Handle_write | // | | |
| +-------------+ +--------------+////////////////////input actor (the input actor) reads the message separated by a newline character from the socket,// The deadline of receiving a message is 30 seconds (auto-disconnect time-out) (the deadline for a complete message is a seconds.)//////The actor responsible for Heartbeat (the Heartbeat Acto R) Heartbeat is sent every 10 seconds (a message with a newline character)//In this example, no deadline is applied to the actor responsible for sending the message (no deadline is applied message sending)//This means that you will not
Send a message and disconnect the connection. Class Client {public:client (boost::asio::io_service& io_service): Stopped_ (False), socket_ (i
O_service), Deadline_ (Io_service), Heartbeat_timer_ (Io_service) {}//Call the client class to initiate the connection process. TheEndpoint iterator would have been obtained using a tcp::resolver.
The port iterator (endpoint iterator) will be obtained from Tcp::resolver.
void Start (Tcp::resolver::iterator endpoint_iter) {//start the Connect actor.
Start_connect (Endpoint_iter); Start the deadline actor.
You will notice that we have not set any deadline from here. Instead, the actor responsible for the connection and the actor responsible for the input will update deadline deadline_.async_wait (Boost::bind (&client::check_deadline) before each asynchronous operation.
, this));
}//This function terminates all actors to close the connection it//This can be called by the user of the client class, or it can be called by the class itself (thus gracefully ending), or it can be called void Stop () due to an "unrecoverable error"
{stopped_ = true;
Socket_.close ();
Deadline_.cancel ();
Heartbeat_timer_.cancel (); } private:void Start_connect (Tcp::resolver::iterator endpoint_iter) {if (Endpoint_iter! = Tcp::resolver
:: Iterator ()) {std::cout << "Trying" << endpoint_iter->endpoint () << "... \ n"; Set a deadline D for the Connect operationEadline_.expires_from_now (boost::p osix_time::seconds (60)); Start the Asynchronous Connect Operation Socket_.async_connect (Endpoint_iter->endpoint (), Boost::bind (&client
:: Handle_connect, this, _1, Endpoint_iter)); } else {//There are no more ports (endpoints) to try.
Terminates the client stop ();
}} void Handle_connect (const boost::system::error_code& EC, Tcp::resolver::iterator Endpoint_iter)
{if (stopped_) return;
The Async_connect () function automatically opens the asynchronous operation of the socket.
If this time closes the socket, the timeout handler (timeout handler) must run.
if (!socket_.is_open ()) {std::cout << "Connect timed out\n";
Try the next available port.
Start_connect (++endpoint_iter); }//Check if the connection operation failed before deadline or if (EC) {std::cout << "Connect error:" << ;
Ec.message () << "\ n"; Before starting a new socket, we need to turn off the previously usedSocket Socket_.close ();
Attempt to connect to the next available port (endpoint) Start_connect (++endpoint_iter); }//Otherwise, we successfully established the connection else {std::cout << "Connected to" << ENDPOINT_ITER-&G
T;endpoint () << "\ n";
Start the input actor.
Start_read ();
Start the heartbeat actor.
Start_write (); }} void Start_read () {//Set a deadline Deadline_.expires_from_now for read operation (boost::p
Osix_time::seconds (30)); Begins an asynchronous operation to read a message with a newline as a new line Boost::asio::async_read_until (socket_, Input_buffer_, ' \ n ', Boost::bind (&
Amp;client::handle_read, this, _1));
} void Handle_read (const boost::system::error_code& EC) {if (stopped_) return;
if (!EC) {//extract the "newline character as New line" message from the buffer std::string lines;
Std::istream is (&input_buffer_); Std::getline (is, line); The empty message is the heartbeat, so we don't care if it (!line.empty ()) {std::cout << "Received:" << l
ine << "\ n";
} start_read ();
} else {std::cout << "Error on Receive:" << ec.message () << "\ n";
Stop ();
}} void Start_write () {if (stopped_) return; Initiates an asynchronous operation to send a heartbeat message Boost::asio::async_write (socket_, Boost::asio::buffer ("\ n", 1), Boost::bind (&CL
Ient::handle_write, this, _1));
} void Handle_write (const boost::system::error_code& EC) {if (stopped_) return; if (!EC) {//wait 10 seconds before sending the next heartbeat Heartbeat_timer_.expires_from_now (boost::p Osix_time::seco
NDS (10));
Heartbeat_timer_.async_wait (Boost::bind (&client::start_write, this));
} else { Std::cout << "Error on Heartbeat:" << ec.message () << "\ n";
Stop ();
}} void Check_deadline () {if (stopped_) return; Check whether the deadline has passed.
We Compare the deadline against//the current time since a new asynchronous operation could have moved the
Deadline before this actor had a chance to run.
Check if deadline has passed//We compare the due date and the current time because a new asynchronous operation may have a deadline before the actor has the opportunity to run. if (Deadline_.expires_at () <= Deadline_timer::traits_type::now ()) {//deadline has been passed. Socket is closed, the
Socket_.close () is canceled with any outstanding asynchronous operations; At this time, there is no active deadline, set the expiry time to infinity//until the next dealline is set, the actor will not take any activity Deadline_.expire
S_at (boost::p osix_time::p os_infin);
}//Let actor return to sleep state deadline_.async_wait (Boost::bind (&client::check_deadline, this)); } Private:bool StoppEd_;
Tcp::socket socket_;
Boost::asio::streambuf Input_buffer_;
Deadline_timer Deadline_;
Deadline_timer Heartbeat_timer_;
};
int main (int argc, char* argv[]) {try {argc = 3;
ARGV[1] = "127.0.0.1";
Argv[2] = "1000";
if (argc! = 3) {std::cerr << "usage:client