]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/asio/example/cpp11/timeouts/blocking_tcp_client.cpp
2 // blocking_tcp_client.cpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~
5 // Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
11 #include <boost/asio/buffer.hpp>
12 #include <boost/asio/connect.hpp>
13 #include <boost/asio/io_context.hpp>
14 #include <boost/asio/ip/tcp.hpp>
15 #include <boost/asio/read_until.hpp>
16 #include <boost/system/system_error.hpp>
17 #include <boost/asio/write.hpp>
22 using boost::asio::ip::tcp
;
24 //----------------------------------------------------------------------
27 // This class manages socket timeouts by running the io_context using the timed
28 // io_context::run_for() member function. Each asynchronous operation is given
29 // a timeout within which it must complete. The socket operations themselves
30 // use lambdas as completion handlers. For a given socket operation, the client
31 // object runs the io_context to block thread execution until the operation
32 // completes or the timeout is reached. If the io_context::run_for() function
33 // times out, the socket is closed and the outstanding asynchronous operation
39 void connect(const std::string
& host
, const std::string
& service
,
40 std::chrono::steady_clock::duration timeout
)
42 // Resolve the host name and service to a list of endpoints.
43 auto endpoints
= tcp::resolver(io_context_
).resolve(host
, service
);
45 // Start the asynchronous operation itself. The lambda that is used as a
46 // callback will update the error variable when the operation completes.
47 // The blocking_udp_client.cpp example shows how you can use std::bind
48 // rather than a lambda.
49 boost::system::error_code error
;
50 boost::asio::async_connect(socket_
, endpoints
,
51 [&](const boost::system::error_code
& result_error
,
52 const tcp::endpoint
& /*result_endpoint*/)
57 // Run the operation until it completes, or until the timeout.
60 // Determine whether a connection was successfully established.
62 throw std::system_error(error
);
65 std::string
read_line(std::chrono::steady_clock::duration timeout
)
67 // Start the asynchronous operation. The lambda that is used as a callback
68 // will update the error and n variables when the operation completes. The
69 // blocking_udp_client.cpp example shows how you can use std::bind rather
71 boost::system::error_code error
;
73 boost::asio::async_read_until(socket_
,
74 boost::asio::dynamic_buffer(input_buffer_
), '\n',
75 [&](const boost::system::error_code
& result_error
,
82 // Run the operation until it completes, or until the timeout.
85 // Determine whether the read completed successfully.
87 throw std::system_error(error
);
89 std::string
line(input_buffer_
.substr(0, n
- 1));
90 input_buffer_
.erase(0, n
);
94 void write_line(const std::string
& line
,
95 std::chrono::steady_clock::duration timeout
)
97 std::string data
= line
+ "\n";
99 // Start the asynchronous operation itself. The lambda that is used as a
100 // callback will update the error variable when the operation completes.
101 // The blocking_udp_client.cpp example shows how you can use std::bind
102 // rather than a lambda.
103 boost::system::error_code error
;
104 boost::asio::async_write(socket_
, boost::asio::buffer(data
),
105 [&](const boost::system::error_code
& result_error
,
106 std::size_t /*result_n*/)
108 error
= result_error
;
111 // Run the operation until it completes, or until the timeout.
114 // Determine whether the read completed successfully.
116 throw std::system_error(error
);
120 void run(std::chrono::steady_clock::duration timeout
)
122 // Restart the io_context, as it may have been left in the "stopped" state
123 // by a previous operation.
124 io_context_
.restart();
126 // Block until the asynchronous operation has completed, or timed out. If
127 // the pending asynchronous operation is a composed operation, the deadline
128 // applies to the entire operation, rather than individual operations on
130 io_context_
.run_for(timeout
);
132 // If the asynchronous operation completed successfully then the io_context
133 // would have been stopped due to running out of work. If it was not
134 // stopped, then the io_context::run_for call must have timed out.
135 if (!io_context_
.stopped())
137 // Close the socket to cancel the outstanding asynchronous operation.
140 // Run the io_context again until the operation completes.
145 boost::asio::io_context io_context_
;
146 tcp::socket socket_
{io_context_
};
147 std::string input_buffer_
;
150 //----------------------------------------------------------------------
152 int main(int argc
, char* argv
[])
158 std::cerr
<< "Usage: blocking_tcp_client <host> <port> <message>\n";
163 c
.connect(argv
[1], argv
[2], std::chrono::seconds(10));
165 auto time_sent
= std::chrono::steady_clock::now();
167 c
.write_line(argv
[3], std::chrono::seconds(10));
171 std::string line
= c
.read_line(std::chrono::seconds(10));
173 // Keep going until we get back the line that was sent.
178 auto time_received
= std::chrono::steady_clock::now();
180 std::cout
<< "Round trip time: ";
181 std::cout
<< std::chrono::duration_cast
<
182 std::chrono::microseconds
>(
183 time_received
- time_sent
).count();
184 std::cout
<< " microseconds\n";
186 catch (std::exception
& e
)
188 std::cerr
<< "Exception: " << e
.what() << "\n";