forked from boostorg/beast
		
	fix #769 The following classes are removed: * handler_type * async_result * async_completion * is_dynamic_buffer * is_const_buffer_sequence * is_mutable_buffer_sequence * handler_alloc Actions Required: * Use BOOST_ASIO_HANDLER_TYPE instead of handler_type * Use BOOST_ASIO_INITFN_RESULT_TYPE instead of async_result * Use boost::asio::async_completion * Use boost::asio::is_dynamic_buffer * Use boost::asio::is_const_buffer_sequence * Use boost::asio::is_mutable_buffer_sequence * boost::asio::associated_allocator_t replaces handler_alloc
		
			
				
	
	
		
			207 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			207 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //
 | |
| // 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
 | |
| //
 | |
| 
 | |
| //------------------------------------------------------------------------------
 | |
| //
 | |
| // Example: WebSocket client, asynchronous
 | |
| //
 | |
| //------------------------------------------------------------------------------
 | |
| 
 | |
| #include <boost/beast/core.hpp>
 | |
| #include <boost/beast/websocket.hpp>
 | |
| #include <boost/asio/connect.hpp>
 | |
| #include <boost/asio/ip/tcp.hpp>
 | |
| #include <cstdlib>
 | |
| #include <functional>
 | |
| #include <iostream>
 | |
| #include <memory>
 | |
| #include <string>
 | |
| 
 | |
| using tcp = boost::asio::ip::tcp;               // from <boost/asio/ip/tcp.hpp>
 | |
| namespace websocket = boost::beast::websocket;  // from <boost/beast/websocket.hpp>
 | |
| 
 | |
| //------------------------------------------------------------------------------
 | |
| 
 | |
| // Report a failure
 | |
| void
 | |
| fail(boost::system::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<tcp::socket> ws_;
 | |
|     boost::beast::multi_buffer buffer_;
 | |
|     std::string host_;
 | |
|     std::string text_;
 | |
| 
 | |
| public:
 | |
|     // Resolver and socket require an io_context
 | |
|     explicit
 | |
|     session(boost::asio::io_context& ioc)
 | |
|         : resolver_(ioc)
 | |
|         , ws_(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,
 | |
|             std::bind(
 | |
|                 &session::on_resolve,
 | |
|                 shared_from_this(),
 | |
|                 std::placeholders::_1,
 | |
|                 std::placeholders::_2));
 | |
|     }
 | |
| 
 | |
|     void
 | |
|     on_resolve(
 | |
|         boost::system::error_code ec,
 | |
|         tcp::resolver::results_type results)
 | |
|     {
 | |
|         if(ec)
 | |
|             return fail(ec, "resolve");
 | |
| 
 | |
|         // Make the connection on the IP address we get from a lookup
 | |
|         boost::asio::async_connect(
 | |
|             ws_.next_layer(),
 | |
|             results.begin(),
 | |
|             results.end(),
 | |
|             std::bind(
 | |
|                 &session::on_connect,
 | |
|                 shared_from_this(),
 | |
|                 std::placeholders::_1));
 | |
|     }
 | |
| 
 | |
|     void
 | |
|     on_connect(boost::system::error_code ec)
 | |
|     {
 | |
|         if(ec)
 | |
|             return fail(ec, "connect");
 | |
| 
 | |
|         // Perform the websocket handshake
 | |
|         ws_.async_handshake(host_, "/",
 | |
|             std::bind(
 | |
|                 &session::on_handshake,
 | |
|                 shared_from_this(),
 | |
|                 std::placeholders::_1));
 | |
|     }
 | |
| 
 | |
|     void
 | |
|     on_handshake(boost::system::error_code ec)
 | |
|     {
 | |
|         if(ec)
 | |
|             return fail(ec, "handshake");
 | |
|         
 | |
|         // Send the message
 | |
|         ws_.async_write(
 | |
|             boost::asio::buffer(text_),
 | |
|             std::bind(
 | |
|                 &session::on_write,
 | |
|                 shared_from_this(),
 | |
|                 std::placeholders::_1,
 | |
|                 std::placeholders::_2));
 | |
|     }
 | |
| 
 | |
|     void
 | |
|     on_write(
 | |
|         boost::system::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_,
 | |
|             std::bind(
 | |
|                 &session::on_read,
 | |
|                 shared_from_this(),
 | |
|                 std::placeholders::_1,
 | |
|                 std::placeholders::_2));
 | |
|     }
 | |
| 
 | |
|     void
 | |
|     on_read(
 | |
|         boost::system::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,
 | |
|             std::bind(
 | |
|                 &session::on_close,
 | |
|                 shared_from_this(),
 | |
|                 std::placeholders::_1));
 | |
|     }
 | |
| 
 | |
|     void
 | |
|     on_close(boost::system::error_code ec)
 | |
|     {
 | |
|         if(ec)
 | |
|             return fail(ec, "close");
 | |
| 
 | |
|         // If we get here then the connection is closed gracefully
 | |
| 
 | |
|         // The buffers() function helps print a ConstBufferSequence
 | |
|         std::cout << boost::beast::buffers(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
 | |
|     boost::asio::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 get operation is complete.
 | |
|     ioc.run();
 | |
| 
 | |
|     return EXIT_SUCCESS;
 | |
| }
 |