0

我正在使用 webscokettpp c++​​ 客户端来读取从网络服务器发布的数据。我有一个带有测试按钮的 ac# UI 应用程序,它调用 c++ 客户端 dll 来获取和显示在套接字上发布的数据。单击测试按钮时,数据第二次在 UI 上正确发布我想关闭现有连接,打开新连接以再次获得结果。但是在第一次运行之后程序永远不会从 c.run(); 返回 在下面的代码中。我正在使用来自https://github.com/zaphoyd/websocketpp/blob/master/examples/echo_client/echo_client.cpp的示例

 #include <websocketpp/config/asio_no_tls_client.hpp>
 #include <websocketpp/client.hpp>

 #include <iostream>

    typedef websocketpp::client<websocketpp::config::asio_client> client;

    using websocketpp::lib::placeholders::_1;
    using websocketpp::lib::placeholders::_2;
    using websocketpp::lib::bind;

    // pull out the type of messages sent by our config
    typedef websocketpp::config::asio_client::message_type::ptr message_ptr;

    // This message handler will be invoked once for each incoming message. It
    // prints the message and then sends a copy of the message back to the server.
    void on_message(client* c, websocketpp::connection_hdl hdl, message_ptr msg) {
        std::cout << "on_message called with hdl: " << hdl.lock().get()
                  << " and message: " << msg->get_payload()
                  << std::endl;

         if(pt.get<std::string>("test") = "close" ){
          //Code reaches here after end of first run but never comes out of c.run()
            c->close(hdl, websocketpp::close::status::normal, "Success");
            hdl.reset();
         }

        websocketpp::lib::error_code ec;

        c->send(hdl, msg->get_payload(), msg->get_opcode(), ec);
        if (ec) {
            std::cout << "Echo failed because: " << ec.message() << std::endl;
        }
    }

    int main(int argc, char* argv[]) {
        // Create a client endpoint
        client c;

        std::string uri = "ws://localhost:9002";

        if (argc == 2) {
            uri = argv[1];
        }

        try {
            // Set logging to be pretty verbose (everything except message payloads)
            c.set_access_channels(websocketpp::log::alevel::all);
            c.clear_access_channels(websocketpp::log::alevel::frame_payload);

            // Initialize ASIO
            c.init_asio();

            // Register our message handler
            c.set_message_handler(bind(&on_message,&c,::_1,::_2));

            websocketpp::lib::error_code ec;
            client::connection_ptr con = c.get_connection(uri, ec);
            if (ec) {
                std::cout << "could not create connection because: " << ec.message() << std::endl;
                return 0;
            }

            // Note that connect here only requests a connection. No network messages are
            // exchanged until the event loop starts running in the next line.
            c.connect(con);

            // Start the ASIO io_service run loop
            // this will cause a single connection to be made to the server. c.run()
            // will exit when this connection is closed.
            c.run();
        } catch (websocketpp::exception const & e) {
            std::cout << e.what() << std::endl;
        }
    }

当条件 if(pt.get("test") = "close") 发生时,我试图找出一种从 c.run() 出来的主要方法的方法。

4

1 回答 1

0

使用客户端时,您需要在单独的线程上调用 run();然后,当您在单独的线程上完成时,这将允许您优雅地停止客户端。IIRC 然后 run() 将退出,这意味着您可以关闭线程并在需要时重新开始。

请参阅此常见问题解答,尤其是“如何干净地退出基于 Asio 传输的程序”部分。停止 exe 以强制关闭连接是一个坏主意,并且可能导致细微的错误。

基于 Asio 传输的客户端和服务器使用 Asio 库的底层 io_service 来处理异步网络操作。io_service 的标准行为是运行直到没有异步操作,然后返回。WebSocket++ 在使用 Asio 传输时,其行为类似于标准的 Asio 应用程序。如果您希望基于 WebSocket++/Asio 的程序停止网络操作并彻底关闭所有套接字,您需要执行以下操作:

对于服务器,调用 websocketpp::transport::asio::endpoint::stop_listening 来启动服务器监听套接字的关闭。对于客户端,如果您使用 websocketpp::transport::asio::endpoint::start_perpetual 启用了永久模式,请使用 websocketpp::transport::asio::endpoint::stop_perpetual 禁用它。对于两者,在所有当前未完成的连接上运行 websocketpp::endpoint::close 或 websocketpp::connection::close 。这将为这些连接启动 WebSocket 关闭握手 等待。Asio 是异步的。当对上述方法(stop_listening、close 等)的调用完成时,服务器仍将处于侦听状态,连接仍将处于活动状态,直到 io_service 开始异步处理套接字和 WebSocket 协议关闭握手。io_service:: run 方法将在所有操作完成后自动干净地退出。警告:Asio 的 io_service 有一个名为 stop 的方法。WebSocket++ 将此方法包装为 websocketpp::transport::asio::endpoint::stop。尽管此操作听起来不错,但它是一种强大且具有破坏性的操作,仅应在特殊情况下使用。如果您使用 io_service::stop 或 endpoint::stop 没有很好的理由,您的程序可能已损坏并且可能表现出不稳定的行为。具体来说,io_service::stop 完全停止事件的处理。这不会给当前操作(例如套接字关闭握手)提供完成的机会。它将使您的套接字处于悬空状态,这可能会引发操作系统级别的超时或其他错误。■ io_service 有一个称为stop 的方法。WebSocket++ 将此方法包装为 websocketpp::transport::asio::endpoint::stop。尽管此操作听起来不错,但它是一种强大且具有破坏性的操作,仅应在特殊情况下使用。如果您使用 io_service::stop 或 endpoint::stop 没有很好的理由,您的程序可能已损坏并且可能表现出不稳定的行为。具体来说,io_service::stop 完全停止事件的处理。这不会给当前操作(例如套接字关闭握手)提供完成的机会。它将使您的套接字处于悬空状态,这可能会引发操作系统级别的超时或其他错误。■ io_service 有一个称为stop 的方法。WebSocket++ 将此方法包装为 websocketpp::transport::asio::endpoint::stop。尽管此操作听起来不错,但它是一种强大且具有破坏性的操作,仅应在特殊情况下使用。如果您使用 io_service::stop 或 endpoint::stop 没有很好的理由,您的程序可能已损坏并且可能表现出不稳定的行为。具体来说,io_service::stop 完全停止事件的处理。这不会给当前操作(例如套接字关闭握手)提供完成的机会。它将使您的套接字处于悬空状态,这可能会引发操作系统级别的超时或其他错误。这是一种强大且具有破坏性的操作,仅应在特殊情况下使用。如果您使用 io_service::stop 或 endpoint::stop 没有很好的理由,您的程序可能已损坏并且可能表现出不稳定的行为。具体来说,io_service::stop 完全停止事件的处理。这不会给当前操作(例如套接字关闭握手)提供完成的机会。它将使您的套接字处于悬空状态,这可能会引发操作系统级别的超时或其他错误。这是一种强大且具有破坏性的操作,仅应在特殊情况下使用。如果您使用 io_service::stop 或 endpoint::stop 没有很好的理由,您的程序可能已损坏并且可能表现出不稳定的行为。具体来说,io_service::stop 完全停止事件的处理。这不会给当前操作(例如套接字关闭握手)提供完成的机会。它将使您的套接字处于悬空状态,这可能会引发操作系统级别的超时或其他错误。这不会给当前操作(例如套接字关闭握手)提供完成的机会。它将使您的套接字处于悬空状态,这可能会引发操作系统级别的超时或其他错误。这不会给当前操作(例如套接字关闭握手)提供完成的机会。它将使您的套接字处于悬空状态,这可能会引发操作系统级别的超时或其他错误。

于 2020-05-24T07:50:18.610 回答