websocket_server_sync.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. //
  2. // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // Official repository: https://github.com/boostorg/beast
  8. //
  9. //------------------------------------------------------------------------------
  10. //
  11. // Example: WebSocket server, synchronous
  12. //
  13. //------------------------------------------------------------------------------
  14. #include <boost/beast/core.hpp>
  15. #include <boost/beast/websocket.hpp>
  16. #include <boost/asio/ip/tcp.hpp>
  17. #include <cstdlib>
  18. #include <functional>
  19. #include <iostream>
  20. #include <string>
  21. #include <thread>
  22. namespace beast = boost::beast; // from <boost/beast.hpp>
  23. namespace http = beast::http; // from <boost/beast/http.hpp>
  24. namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
  25. namespace net = boost::asio; // from <boost/asio.hpp>
  26. using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
  27. //------------------------------------------------------------------------------
  28. // Echoes back all received WebSocket messages
  29. void
  30. do_session(tcp::socket& socket)
  31. {
  32. try
  33. {
  34. // Construct the stream by moving in the socket
  35. websocket::stream<tcp::socket> ws{std::move(socket)};
  36. // Set a decorator to change the Server of the handshake
  37. ws.set_option(websocket::stream_base::decorator(
  38. [](websocket::response_type& res)
  39. {
  40. res.set(http::field::server,
  41. std::string(BOOST_BEAST_VERSION_STRING) +
  42. " websocket-server-sync");
  43. }));
  44. // Accept the websocket handshake
  45. ws.accept();
  46. for(;;)
  47. {
  48. // This buffer will hold the incoming message
  49. beast::flat_buffer buffer;
  50. // Read a message
  51. ws.read(buffer);
  52. // Echo the message back
  53. ws.text(ws.got_text());
  54. ws.write(buffer.data());
  55. }
  56. }
  57. catch(beast::system_error const& se)
  58. {
  59. // This indicates that the session was closed
  60. if(se.code() != websocket::error::closed)
  61. std::cerr << "Error: " << se.code().message() << std::endl;
  62. }
  63. catch(std::exception const& e)
  64. {
  65. std::cerr << "Error: " << e.what() << std::endl;
  66. }
  67. }
  68. //------------------------------------------------------------------------------
  69. int main(int argc, char* argv[])
  70. {
  71. try
  72. {
  73. // Check command line arguments.
  74. if (argc != 3)
  75. {
  76. std::cerr <<
  77. "Usage: websocket-server-sync <address> <port>\n" <<
  78. "Example:\n" <<
  79. " websocket-server-sync 0.0.0.0 8080\n";
  80. return EXIT_FAILURE;
  81. }
  82. auto const address = net::ip::make_address(argv[1]);
  83. auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
  84. // The io_context is required for all I/O
  85. net::io_context ioc{1};
  86. // The acceptor receives incoming connections
  87. tcp::acceptor acceptor{ioc, {address, port}};
  88. for(;;)
  89. {
  90. // This will receive the new connection
  91. tcp::socket socket{ioc};
  92. // Block until we get a connection
  93. acceptor.accept(socket);
  94. // Launch the session, transferring ownership of the socket
  95. std::thread{std::bind(
  96. &do_session,
  97. std::move(socket))}.detach();
  98. }
  99. }
  100. catch (const std::exception& e)
  101. {
  102. std::cerr << "Error: " << e.what() << std::endl;
  103. return EXIT_FAILURE;
  104. }
  105. }