summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/asio/src/examples/cpp03/timeouts/blocking_tcp_client.cpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/asio/src/examples/cpp03/timeouts/blocking_tcp_client.cpp')
-rw-r--r--3rdparty/asio/src/examples/cpp03/timeouts/blocking_tcp_client.cpp191
1 files changed, 191 insertions, 0 deletions
diff --git a/3rdparty/asio/src/examples/cpp03/timeouts/blocking_tcp_client.cpp b/3rdparty/asio/src/examples/cpp03/timeouts/blocking_tcp_client.cpp
new file mode 100644
index 00000000000..67d0bcc7604
--- /dev/null
+++ b/3rdparty/asio/src/examples/cpp03/timeouts/blocking_tcp_client.cpp
@@ -0,0 +1,191 @@
+//
+// blocking_tcp_client.cpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include "asio/buffer.hpp"
+#include "asio/connect.hpp"
+#include "asio/io_context.hpp"
+#include "asio/ip/tcp.hpp"
+#include "asio/read_until.hpp"
+#include "asio/system_error.hpp"
+#include "asio/write.hpp"
+#include <cstdlib>
+#include <iostream>
+#include <string>
+#include <boost/lambda/bind.hpp>
+#include <boost/lambda/lambda.hpp>
+
+using asio::ip::tcp;
+using boost::lambda::bind;
+using boost::lambda::var;
+using boost::lambda::_1;
+using boost::lambda::_2;
+
+//----------------------------------------------------------------------
+
+//
+// This class manages socket timeouts by running the io_context using the timed
+// io_context::run_for() member function. Each asynchronous operation is given
+// a timeout within which it must complete. The socket operations themselves
+// use boost::lambda function objects as completion handlers. For a given
+// socket operation, the client object runs the io_context to block thread
+// execution until the operation completes or the timeout is reached. If the
+// io_context::run_for() function times out, the socket is closed and the
+// outstanding asynchronous operation is cancelled.
+//
+class client
+{
+public:
+ client()
+ : socket_(io_context_)
+ {
+ }
+
+ void connect(const std::string& host, const std::string& service,
+ asio::chrono::steady_clock::duration timeout)
+ {
+ // Resolve the host name and service to a list of endpoints.
+ tcp::resolver::results_type endpoints =
+ tcp::resolver(io_context_).resolve(host, service);
+
+ // Start the asynchronous operation itself. The boost::lambda function
+ // object is used as a callback and will update the ec variable when the
+ // operation completes. The blocking_udp_client.cpp example shows how you
+ // can use boost::bind rather than boost::lambda.
+ asio::error_code ec;
+ asio::async_connect(socket_, endpoints, var(ec) = _1);
+
+ // Run the operation until it completes, or until the timeout.
+ run(timeout);
+
+ // Determine whether a connection was successfully established.
+ if (ec)
+ throw asio::system_error(ec);
+ }
+
+ std::string read_line(asio::chrono::steady_clock::duration timeout)
+ {
+ // Start the asynchronous operation. The boost::lambda function object is
+ // used as a callback and will update the ec variable when the operation
+ // completes. The blocking_udp_client.cpp example shows how you can use
+ // boost::bind rather than boost::lambda.
+ asio::error_code ec;
+ std::size_t n = 0;
+ asio::async_read_until(socket_,
+ asio::dynamic_buffer(input_buffer_),
+ '\n', (var(ec) = _1, var(n) = _2));
+
+ // Run the operation until it completes, or until the timeout.
+ run(timeout);
+
+ // Determine whether the read completed successfully.
+ if (ec)
+ throw asio::system_error(ec);
+
+ std::string line(input_buffer_.substr(0, n - 1));
+ input_buffer_.erase(0, n);
+ return line;
+ }
+
+ void write_line(const std::string& line,
+ asio::chrono::steady_clock::duration timeout)
+ {
+ std::string data = line + "\n";
+
+ // Start the asynchronous operation. The boost::lambda function object is
+ // used as a callback and will update the ec variable when the operation
+ // completes. The blocking_udp_client.cpp example shows how you can use
+ // boost::bind rather than boost::lambda.
+ asio::error_code ec;
+ asio::async_write(socket_, asio::buffer(data), var(ec) = _1);
+
+ // Run the operation until it completes, or until the timeout.
+ run(timeout);
+
+ // Determine whether the read completed successfully.
+ if (ec)
+ throw asio::system_error(ec);
+ }
+
+private:
+ void run(asio::chrono::steady_clock::duration timeout)
+ {
+ // Restart the io_context, as it may have been left in the "stopped" state
+ // by a previous operation.
+ io_context_.restart();
+
+ // Block until the asynchronous operation has completed, or timed out. If
+ // the pending asynchronous operation is a composed operation, the deadline
+ // applies to the entire operation, rather than individual operations on
+ // the socket.
+ io_context_.run_for(timeout);
+
+ // If the asynchronous operation completed successfully then the io_context
+ // would have been stopped due to running out of work. If it was not
+ // stopped, then the io_context::run_for call must have timed out.
+ if (!io_context_.stopped())
+ {
+ // Close the socket to cancel the outstanding asynchronous operation.
+ socket_.close();
+
+ // Run the io_context again until the operation completes.
+ io_context_.run();
+ }
+ }
+
+ asio::io_context io_context_;
+ tcp::socket socket_;
+ std::string input_buffer_;
+};
+
+//----------------------------------------------------------------------
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 4)
+ {
+ std::cerr << "Usage: blocking_tcp_client <host> <port> <message>\n";
+ return 1;
+ }
+
+ client c;
+ c.connect(argv[1], argv[2], asio::chrono::seconds(10));
+
+ asio::chrono::steady_clock::time_point time_sent =
+ asio::chrono::steady_clock::now();
+
+ c.write_line(argv[3], asio::chrono::seconds(10));
+
+ for (;;)
+ {
+ std::string line = c.read_line(asio::chrono::seconds(10));
+
+ // Keep going until we get back the line that was sent.
+ if (line == argv[3])
+ break;
+ }
+
+ asio::chrono::steady_clock::time_point time_received =
+ asio::chrono::steady_clock::now();
+
+ std::cout << "Round trip time: ";
+ std::cout << asio::chrono::duration_cast<
+ asio::chrono::microseconds>(
+ time_received - time_sent).count();
+ std::cout << " microseconds\n";
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}