// // client.cpp // ~~~~~~~~~~ // // Copyright (c) 2003-2023 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 #include #include #include #include "connection.hpp" // Must come before boost/serialization headers. #include #include "stock.hpp" namespace s11n_example { /// Downloads stock quote information from a server. class client { public: /// Constructor starts the asynchronous connect operation. client(asio::io_context& io_context, const std::string& host, const std::string& service) : connection_(io_context.get_executor()) { // Resolve the host name into an IP address. asio::ip::tcp::resolver resolver(io_context); asio::ip::tcp::resolver::query query(host, service); asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); // Start an asynchronous connect operation. asio::async_connect(connection_.socket(), endpoint_iterator, boost::bind(&client::handle_connect, this, asio::placeholders::error)); } /// Handle completion of a connect operation. void handle_connect(const asio::error_code& e) { if (!e) { // Successfully established connection. Start operation to read the list // of stocks. The connection::async_read() function will automatically // decode the data that is read from the underlying socket. connection_.async_read(stocks_, boost::bind(&client::handle_read, this, asio::placeholders::error)); } else { // An error occurred. Log it and return. Since we are not starting a new // operation the io_context will run out of work to do and the client will // exit. std::cerr << e.message() << std::endl; } } /// Handle completion of a read operation. void handle_read(const asio::error_code& e) { if (!e) { // Print out the data that was received. for (std::size_t i = 0; i < stocks_.size(); ++i) { std::cout << "Stock number " << i << "\n"; std::cout << " code: " << stocks_[i].code << "\n"; std::cout << " name: " << stocks_[i].name << "\n"; std::cout << " open_price: " << stocks_[i].open_price << "\n"; std::cout << " high_price: " << stocks_[i].high_price << "\n"; std::cout << " low_price: " << stocks_[i].low_price << "\n"; std::cout << " last_price: " << stocks_[i].last_price << "\n"; std::cout << " buy_price: " << stocks_[i].buy_price << "\n"; std::cout << " buy_quantity: " << stocks_[i].buy_quantity << "\n"; std::cout << " sell_price: " << stocks_[i].sell_price << "\n"; std::cout << " sell_quantity: " << stocks_[i].sell_quantity << "\n"; } } else { // An error occurred. std::cerr << e.message() << std::endl; } // Since we are not starting a new operation the io_context will run out of // work to do and the client will exit. } private: /// The connection to the server. connection connection_; /// The data received from the server. std::vector stocks_; }; } // namespace s11n_example int main(int argc, char* argv[]) { try { // Check command line arguments. if (argc != 3) { std::cerr << "Usage: client " << std::endl; return 1; } asio::io_context io_context; s11n_example::client client(io_context, argv[1], argv[2]); io_context.run(); } catch (std::exception& e) { std::cerr << e.what() << std::endl; } return 0; }