| 
									
										
										
										
											2017-08-04 19:55:28 -07:00
										 |  |  | //
 | 
					
						
							|  |  |  | // 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 server, synchronous
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //------------------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <boost/beast/core.hpp>
 | 
					
						
							|  |  |  | #include <boost/beast/websocket.hpp>
 | 
					
						
							|  |  |  | #include <boost/asio/ip/tcp.hpp>
 | 
					
						
							|  |  |  | #include <cstdlib>
 | 
					
						
							|  |  |  | #include <functional>
 | 
					
						
							|  |  |  | #include <iostream>
 | 
					
						
							|  |  |  | #include <string>
 | 
					
						
							|  |  |  | #include <thread>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | using tcp = boost::asio::ip::tcp;               // from <boost/asio/ip/tcp.hpp>
 | 
					
						
							|  |  |  | namespace websocket = boost::beast::websocket;  // from <boost/beast/websocket.hpp>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //------------------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Echoes back all received WebSocket messages
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | do_session(tcp::socket& socket) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     try | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // Construct the stream by moving in the socket
 | 
					
						
							|  |  |  |         websocket::stream<tcp::socket> ws{std::move(socket)}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Accept the websocket handshake
 | 
					
						
							|  |  |  |         ws.accept(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for(;;) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             // This buffer will hold the incoming message
 | 
					
						
							|  |  |  |             boost::beast::multi_buffer buffer; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // Read a message
 | 
					
						
							|  |  |  |             ws.read(buffer); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // Echo the message back
 | 
					
						
							|  |  |  |             ws.text(ws.got_text()); | 
					
						
							|  |  |  |             ws.write(buffer.data()); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     catch(boost::system::system_error const& se) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // This indicates that the session was closed
 | 
					
						
							|  |  |  |         if(se.code() != websocket::error::closed) | 
					
						
							|  |  |  |             std::cerr << "Error: " << se.code().message() << std::endl; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     catch(std::exception const& e) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         std::cerr << "Error: " << e.what() << std::endl; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //------------------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int main(int argc, char* argv[]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     try | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // Check command line arguments.
 | 
					
						
							|  |  |  |         if (argc != 3) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             std::cerr << | 
					
						
							|  |  |  |                 "Usage: websocket-server-sync <address> <port>\n" << | 
					
						
							|  |  |  |                 "Example:\n" << | 
					
						
							|  |  |  |                 "    websocket-server-sync 0.0.0.0 8080\n"; | 
					
						
							|  |  |  |             return EXIT_FAILURE; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-09-07 07:39:52 -07:00
										 |  |  |         auto const address = boost::asio::ip::make_address(argv[1]); | 
					
						
							| 
									
										
										
										
											2017-08-04 19:55:28 -07:00
										 |  |  |         auto const port = static_cast<unsigned short>(std::atoi(argv[2])); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-07 07:39:52 -07:00
										 |  |  |         // The io_context is required for all I/O
 | 
					
						
							|  |  |  |         boost::asio::io_context ioc{1}; | 
					
						
							| 
									
										
										
										
											2017-08-04 19:55:28 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // The acceptor receives incoming connections
 | 
					
						
							| 
									
										
										
										
											2017-09-07 07:39:52 -07:00
										 |  |  |         tcp::acceptor acceptor{ioc, {address, port}}; | 
					
						
							| 
									
										
										
										
											2017-08-04 19:55:28 -07:00
										 |  |  |         for(;;) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             // This will receive the new connection
 | 
					
						
							| 
									
										
										
										
											2017-09-07 07:39:52 -07:00
										 |  |  |             tcp::socket socket{ioc}; | 
					
						
							| 
									
										
										
										
											2017-08-04 19:55:28 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |             // Block until we get a connection
 | 
					
						
							|  |  |  |             acceptor.accept(socket); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // Launch the session, transferring ownership of the socket
 | 
					
						
							|  |  |  |             std::thread{std::bind( | 
					
						
							|  |  |  |                 &do_session, | 
					
						
							|  |  |  |                 std::move(socket))}.detach(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     catch (const std::exception& e) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         std::cerr << "Error: " << e.what() << std::endl; | 
					
						
							|  |  |  |         return EXIT_FAILURE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |