websocket 为什么出现未初始化异常?

rqqzpn5f  于 2023-08-05  发布在  其他
关注(0)|答案(1)|浏览(92)

下面的代码在**ws.handshake(url,“/”)**调用中抛出一个未初始化的异常…我是Beast的新手,但这主要是从工作示例代码中复制的。有人知道为什么会这样吗???我真的很感激你能帮我解决这个问题!:)

std::string cert = 
      "# MPU5 Radio - Serial #35409\n"
      "-----BEGIN CERTIFICATE-----\n"
      "MIIBXzCB5QIJAIXhtL/+cBGIMAoGCCqGSM49BAMDMB0xGzAZBgNVBAMMEldhdmUg\n"
      "UmVsYXkgU2VsZi1DQTAeFw03MDAxMDEwMDAwMjJaFw03MTAxMDEwMDAwMjJaMBUx\n"
      "EzARBgNVBAMMCldhdmUgUmVsYXkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATHCIq1\n"
      "YHbWl7rJ3w/6ekiGYq5+tb1ip1Tkm4sX7yPW62QZ5rZQp05I+B8p1u6dtjsj/EvJ\n"
      "YDvqqrezL0oWIgfL3X/MHSvOMiLcXzf7ooXZgkc/t19WnmdfoyS1+UPQTt0wCgYI\n"
      "KoZIzj0EAwMDaQAwZgIxANjEbIEOmrNG+M8mwT0/cx9A2JldSOz87G7N5f0aB8iF\n"
      "gMok+H4D/Rmeje6+MakDNAIxALYeNUw4++hyLDRTxWu37QZOoK0PprdaRQiGOsER\n"
      "T+1di9sgMZ+8aQjGlgTSeKdmUg==\n"
      "-----END CERTIFICATE-----";
      
   static std::string response = "ERROR!"; // pessimistic start
   boost::system::error_code ec;
   
   std::string url = "wss://" + ip_addr ;

   try
   {
      ssl::context ctx{ssl::context::tlsv12};
      ctx.set_options(boost::asio::ssl::context::default_workarounds |
                      boost::asio::ssl::context::no_sslv2 |
                      boost::asio::ssl::context::single_dh_use);
      ctx.set_verify_mode(boost::asio::ssl::context::verify_peer | boost::asio::ssl::context::verify_fail_if_no_peer_cert);
      ctx.load_verify_file("/root/catkin_ws/src/radio_bridge/certs/35409.pem");
      
      // The io_context is required for all I/O
      net::io_context ioc;
      
      // These objects perform our I/O
      tcp::resolver resolver{ioc};
      websocket::stream<beast::ssl_stream<beast::tcp_stream>> ws{ioc, ctx};
      
      // Look up the domain name
      auto const results = resolver.resolve(ip_addr, "443");
      
      // Make the connection on the IP address we get from a lookup
      auto ep = beast::get_lowest_layer(ws).connect(results); 
            
      url += std::string(":443");

      // 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-coro");
         }));

      // Perform the websocket handshake
      std::cout << "URL: " << url << std::endl;

      ROS_INFO("before handshake");
      ws.handshake(url, "/");
      ROS_INFO("after handshake");
      
      // Send the message
      ws.write(net::buffer(std::string(request)));

      // This buffer will hold the incoming message
      beast::flat_buffer buffer;

      // Read a message into our buffer
      ws.read(buffer);

      // Close the WebSocket connection
      sleep(10);
      ws.close(websocket::close_code::normal);

      // 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;
   }
   catch(std::exception const& e)
   {
      std::cerr << "Error: " << e.what() << std::endl;
   }
   return response;

字符串
就像我说的,我是Beast的新手,这段代码大部分是从现有示例中复制/粘贴的。我只是不明白应该进行什么进一步的初始化...

9avjhtql

9avjhtql1#

您正在连接TCP流:

beast::tcp_stream& ll = beast::get_lowest_layer(ws);
auto ep = ll.connect(results);

字符串
这不会初始化SSL会话。您错过了SSL握手,例如

ws.next_layer().handshake(ssl::stream_base::handshake_type::client);


这是我的独立草图供参考。注意我不能测试这个,因为我没有“Wave Relay Self-CA”或任何由它签署的证书。但它可能会帮助你连接一些点:

**Live On Coliru**第一个字符

#include <boost/beast.hpp>
#include <boost/beast/ssl.hpp>
#include <iostream>

void ROS_INFO(auto const& msg) {
    std::cerr << "ROS_INFO: " << msg << std::endl;
}

auto foo(std::string ip_addr, std::string const& request) {
    namespace beast     = boost::beast;
    namespace net       = boost::asio;
    namespace websocket = beast::websocket;
    namespace http      = beast::http;
    namespace ssl       = net::ssl;
    using net::ip::tcp;

    std::string cert = "# MPU5 Radio - Serial #35409\n"
                       "-----BEGIN CERTIFICATE-----\n"
                       "MIIBXzCB5QIJAIXhtL/+cBGIMAoGCCqGSM49BAMDMB0xGzAZBgNVBAMMEldhdmUg\n"
                       "UmVsYXkgU2VsZi1DQTAeFw03MDAxMDEwMDAwMjJaFw03MTAxMDEwMDAwMjJaMBUx\n"
                       "EzARBgNVBAMMCldhdmUgUmVsYXkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATHCIq1\n"
                       "YHbWl7rJ3w/6ekiGYq5+tb1ip1Tkm4sX7yPW62QZ5rZQp05I+B8p1u6dtjsj/EvJ\n"
                       "YDvqqrezL0oWIgfL3X/MHSvOMiLcXzf7ooXZgkc/t19WnmdfoyS1+UPQTt0wCgYI\n"
                       "KoZIzj0EAwMDaQAwZgIxANjEbIEOmrNG+M8mwT0/cx9A2JldSOz87G7N5f0aB8iF\n"
                       "gMok+H4D/Rmeje6+MakDNAIxALYeNUw4++hyLDRTxWu37QZOoK0PprdaRQiGOsER\n"
                       "T+1di9sgMZ+8aQjGlgTSeKdmUg==\n"
                       "-----END CERTIFICATE-----";

    static std::string        response = "ERROR!"; // pessimistic start
    boost::system::error_code ec;

    std::string url = "wss://" + ip_addr;

    try {
        ssl::context ctx{ssl::context::tlsv12};
        ctx.set_options(boost::asio::ssl::context::default_workarounds | boost::asio::ssl::context::no_sslv2 |
                        boost::asio::ssl::context::single_dh_use);
        ctx.set_verify_mode(boost::asio::ssl::context::verify_peer |
                            boost::asio::ssl::context::verify_fail_if_no_peer_cert);
        ctx.load_verify_file("/root/catkin_ws/src/radio_bridge/certs/35409.pem");

        // The io_context is required for all I/O
        net::io_context ioc;

        // These objects perform our I/O
        tcp::resolver                                           resolver{ioc};
        websocket::stream<beast::ssl_stream<beast::tcp_stream>> ws{ioc, ctx};

        // Look up the domain name
        auto results = resolver.resolve(ip_addr, "443");

        // Make the connection on the IP address we get from a lookup
        beast::tcp_stream& ll = beast::get_lowest_layer(ws);
        auto ep = ll.connect(results);

        ws.next_layer().handshake(ssl::stream_base::handshake_type::client);

        url += std::string(":443");

        // 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-coro");
        }));

        // Perform the websocket handshake
        std::cout << "URL: " << url << std::endl;

        ROS_INFO("before handshake");
        ws.handshake(url, "/");
        ROS_INFO("after handshake");

        // Send the message
        ws.write(net::buffer(std::string(request)));

        // This buffer will hold the incoming message
        beast::flat_buffer buffer;

        // Read a message into our buffer
        ws.read(buffer);

        // Close the WebSocket connection
        sleep(10);
        ws.close(websocket::close_code::normal);

        // 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;
   }
   catch(std::exception const& e)
   {
      std::cerr << "Error: " << e.what() << std::endl;
   }
   return response;
}

int main() {
    foo("127.0.0.1", "test hello world");
}

相关问题