diff options
Diffstat (limited to 'src/boost/libs/beast/example/websocket/client/async')
3 files changed, 256 insertions, 0 deletions
diff --git a/src/boost/libs/beast/example/websocket/client/async/CMakeLists.txt b/src/boost/libs/beast/example/websocket/client/async/CMakeLists.txt new file mode 100644 index 00000000..cc643407 --- /dev/null +++ b/src/boost/libs/beast/example/websocket/client/async/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail 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) +# +# Official repository: https://github.com/boostorg/beast +# + +GroupSources(include/boost/beast beast) +GroupSources(example/websocket/client/async "/") + +add_executable (websocket-client-async + ${BOOST_BEAST_FILES} + Jamfile + websocket_client_async.cpp +) + +target_link_libraries(websocket-client-async + lib-asio + lib-beast) + +set_property(TARGET websocket-client-async PROPERTY FOLDER "example-websocket-client") diff --git a/src/boost/libs/beast/example/websocket/client/async/Jamfile b/src/boost/libs/beast/example/websocket/client/async/Jamfile new file mode 100644 index 00000000..e5359db3 --- /dev/null +++ b/src/boost/libs/beast/example/websocket/client/async/Jamfile @@ -0,0 +1,15 @@ +# +# Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail 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) +# +# Official repository: https://github.com/boostorg/beast +# + +exe websocket-client-async : + websocket_client_async.cpp + : + <variant>coverage:<build>no + <variant>ubasan:<build>no + ; diff --git a/src/boost/libs/beast/example/websocket/client/async/websocket_client_async.cpp b/src/boost/libs/beast/example/websocket/client/async/websocket_client_async.cpp new file mode 100644 index 00000000..15b127d3 --- /dev/null +++ b/src/boost/libs/beast/example/websocket/client/async/websocket_client_async.cpp @@ -0,0 +1,218 @@ +// +// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail 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) +// +// Official repository: https://github.com/boostorg/beast +// + +//------------------------------------------------------------------------------ +// +// Example: WebSocket client, asynchronous +// +//------------------------------------------------------------------------------ + +#include <boost/beast/core.hpp> +#include <boost/beast/websocket.hpp> +#include <boost/asio/strand.hpp> +#include <cstdlib> +#include <functional> +#include <iostream> +#include <memory> +#include <string> + +namespace beast = boost::beast; // from <boost/beast.hpp> +namespace http = beast::http; // from <boost/beast/http.hpp> +namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp> +namespace net = boost::asio; // from <boost/asio.hpp> +using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp> + +//------------------------------------------------------------------------------ + +// Report a failure +void +fail(beast::error_code ec, char const* what) +{ + std::cerr << what << ": " << ec.message() << "\n"; +} + +// Sends a WebSocket message and prints the response +class session : public std::enable_shared_from_this<session> +{ + tcp::resolver resolver_; + websocket::stream<beast::tcp_stream> ws_; + beast::flat_buffer buffer_; + std::string host_; + std::string text_; + +public: + // Resolver and socket require an io_context + explicit + session(net::io_context& ioc) + : resolver_(net::make_strand(ioc)) + , ws_(net::make_strand(ioc)) + { + } + + // Start the asynchronous operation + void + run( + char const* host, + char const* port, + char const* text) + { + // Save these for later + host_ = host; + text_ = text; + + // Look up the domain name + resolver_.async_resolve( + host, + port, + beast::bind_front_handler( + &session::on_resolve, + shared_from_this())); + } + + void + on_resolve( + beast::error_code ec, + tcp::resolver::results_type results) + { + if(ec) + return fail(ec, "resolve"); + + // Set the timeout for the operation + beast::get_lowest_layer(ws_).expires_after(std::chrono::seconds(30)); + + // Make the connection on the IP address we get from a lookup + beast::get_lowest_layer(ws_).async_connect( + results, + beast::bind_front_handler( + &session::on_connect, + shared_from_this())); + } + + void + on_connect(beast::error_code ec, tcp::resolver::results_type::endpoint_type) + { + if(ec) + return fail(ec, "connect"); + + // Turn off the timeout on the tcp_stream, because + // the websocket stream has its own timeout system. + beast::get_lowest_layer(ws_).expires_never(); + + // Set suggested timeout settings for the websocket + ws_.set_option( + websocket::stream_base::timeout::suggested( + beast::role_type::client)); + + // Set a decorator to change the User-Agent of the handshake + ws_.set_option(websocket::stream_base::decorator( + [](websocket::request_type& req) + { + req.set(http::field::user_agent, + std::string(BOOST_BEAST_VERSION_STRING) + + " websocket-client-async"); + })); + + // Perform the websocket handshake + ws_.async_handshake(host_, "/", + beast::bind_front_handler( + &session::on_handshake, + shared_from_this())); + } + + void + on_handshake(beast::error_code ec) + { + if(ec) + return fail(ec, "handshake"); + + // Send the message + ws_.async_write( + net::buffer(text_), + beast::bind_front_handler( + &session::on_write, + shared_from_this())); + } + + void + on_write( + beast::error_code ec, + std::size_t bytes_transferred) + { + boost::ignore_unused(bytes_transferred); + + if(ec) + return fail(ec, "write"); + + // Read a message into our buffer + ws_.async_read( + buffer_, + beast::bind_front_handler( + &session::on_read, + shared_from_this())); + } + + void + on_read( + beast::error_code ec, + std::size_t bytes_transferred) + { + boost::ignore_unused(bytes_transferred); + + if(ec) + return fail(ec, "read"); + + // Close the WebSocket connection + ws_.async_close(websocket::close_code::normal, + beast::bind_front_handler( + &session::on_close, + shared_from_this())); + } + + void + on_close(beast::error_code ec) + { + if(ec) + return fail(ec, "close"); + + // If we get here then the connection is closed gracefully + + // The make_printable() function helps print a ConstBufferSequence + std::cout << beast::make_printable(buffer_.data()) << std::endl; + } +}; + +//------------------------------------------------------------------------------ + +int main(int argc, char** argv) +{ + // Check command line arguments. + if(argc != 4) + { + std::cerr << + "Usage: websocket-client-async <host> <port> <text>\n" << + "Example:\n" << + " websocket-client-async echo.websocket.org 80 \"Hello, world!\"\n"; + return EXIT_FAILURE; + } + auto const host = argv[1]; + auto const port = argv[2]; + auto const text = argv[3]; + + // The io_context is required for all I/O + net::io_context ioc; + + // Launch the asynchronous operation + std::make_shared<session>(ioc)->run(host, port, text); + + // Run the I/O service. The call will return when + // the socket is closed. + ioc.run(); + + return EXIT_SUCCESS; +} |