]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/asio/example/cpp03/timeouts/blocking_tcp_client.cpp
2 // blocking_tcp_client.cpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~
5 // Copyright (c) 2003-2022 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>
21 #include <boost/lambda/bind.hpp>
22 #include <boost/lambda/lambda.hpp>
24 using boost::asio::ip::tcp
;
25 using boost::lambda::bind
;
26 using boost::lambda::var
;
27 using boost::lambda::_1
;
28 using boost::lambda::_2
;
30 //----------------------------------------------------------------------
33 // This class manages socket timeouts by running the io_context using the timed
34 // io_context::run_for() member function. Each asynchronous operation is given
35 // a timeout within which it must complete. The socket operations themselves
36 // use boost::lambda function objects as completion handlers. For a given
37 // socket operation, the client object runs the io_context to block thread
38 // execution until the operation completes or the timeout is reached. If the
39 // io_context::run_for() function times out, the socket is closed and the
40 // outstanding asynchronous operation is cancelled.
46 : socket_(io_context_
)
50 void connect(const std::string
& host
, const std::string
& service
,
51 boost::asio::chrono::steady_clock::duration timeout
)
53 // Resolve the host name and service to a list of endpoints.
54 tcp::resolver::results_type endpoints
=
55 tcp::resolver(io_context_
).resolve(host
, service
);
57 // Start the asynchronous operation itself. The boost::lambda function
58 // object is used as a callback and will update the ec variable when the
59 // operation completes. The blocking_udp_client.cpp example shows how you
60 // can use boost::bind rather than boost::lambda.
61 boost::system::error_code ec
;
62 boost::asio::async_connect(socket_
, endpoints
, var(ec
) = _1
);
64 // Run the operation until it completes, or until the timeout.
67 // Determine whether a connection was successfully established.
69 throw boost::system::system_error(ec
);
72 std::string
read_line(boost::asio::chrono::steady_clock::duration timeout
)
74 // Start the asynchronous operation. The boost::lambda function object is
75 // used as a callback and will update the ec variable when the operation
76 // completes. The blocking_udp_client.cpp example shows how you can use
77 // boost::bind rather than boost::lambda.
78 boost::system::error_code ec
;
80 boost::asio::async_read_until(socket_
,
81 boost::asio::dynamic_buffer(input_buffer_
),
82 '\n', (var(ec
) = _1
, var(n
) = _2
));
84 // Run the operation until it completes, or until the timeout.
87 // Determine whether the read completed successfully.
89 throw boost::system::system_error(ec
);
91 std::string
line(input_buffer_
.substr(0, n
- 1));
92 input_buffer_
.erase(0, n
);
96 void write_line(const std::string
& line
,
97 boost::asio::chrono::steady_clock::duration timeout
)
99 std::string data
= line
+ "\n";
101 // Start the asynchronous operation. The boost::lambda function object is
102 // used as a callback and will update the ec variable when the operation
103 // completes. The blocking_udp_client.cpp example shows how you can use
104 // boost::bind rather than boost::lambda.
105 boost::system::error_code ec
;
106 boost::asio::async_write(socket_
, boost::asio::buffer(data
), var(ec
) = _1
);
108 // Run the operation until it completes, or until the timeout.
111 // Determine whether the read completed successfully.
113 throw boost::system::system_error(ec
);
117 void run(boost::asio::chrono::steady_clock::duration timeout
)
119 // Restart the io_context, as it may have been left in the "stopped" state
120 // by a previous operation.
121 io_context_
.restart();
123 // Block until the asynchronous operation has completed, or timed out. If
124 // the pending asynchronous operation is a composed operation, the deadline
125 // applies to the entire operation, rather than individual operations on
127 io_context_
.run_for(timeout
);
129 // If the asynchronous operation completed successfully then the io_context
130 // would have been stopped due to running out of work. If it was not
131 // stopped, then the io_context::run_for call must have timed out.
132 if (!io_context_
.stopped())
134 // Close the socket to cancel the outstanding asynchronous operation.
137 // Run the io_context again until the operation completes.
142 boost::asio::io_context io_context_
;
144 std::string input_buffer_
;
147 //----------------------------------------------------------------------
149 int main(int argc
, char* argv
[])
155 std::cerr
<< "Usage: blocking_tcp_client <host> <port> <message>\n";
160 c
.connect(argv
[1], argv
[2], boost::asio::chrono::seconds(10));
162 boost::asio::chrono::steady_clock::time_point time_sent
=
163 boost::asio::chrono::steady_clock::now();
165 c
.write_line(argv
[3], boost::asio::chrono::seconds(10));
169 std::string line
= c
.read_line(boost::asio::chrono::seconds(10));
171 // Keep going until we get back the line that was sent.
176 boost::asio::chrono::steady_clock::time_point time_received
=
177 boost::asio::chrono::steady_clock::now();
179 std::cout
<< "Round trip time: ";
180 std::cout
<< boost::asio::chrono::duration_cast
<
181 boost::asio::chrono::microseconds
>(
182 time_received
- time_sent
).count();
183 std::cout
<< " microseconds\n";
185 catch (std::exception
& e
)
187 std::cerr
<< "Exception: " << e
.what() << "\n";