从C#UI应用程序

时间:2016-10-06 21:43:23

标签: c++ sockets websocket libwebsockets

我正在使用webscokettpp c ++客户端来读取从Web服务器发布的数据。我有一个带有测试按钮的c#UI应用程序,它调用c ++ client 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;
        }
    }

我试图找出一种主要方法,当条件为(pt.get(&#34; test&#34;)=&#34; close&#34;)时,从c.run()中出来的方法发生的情况。

1 个答案:

答案 0 :(得分:0)

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

请参见this FAQ,尤其是“如何彻底退出基于Asio Transport的程序”部分。停止exe强制关闭连接是一个坏主意,并且可能导致细微的错误。

基于Asio传输的客户端和服务器使用Asio库的基础io_service来处理异步网络操作。 io_service的标准行为是一直运行,直到没有异步操作再返回。当使用Asio传输时,WebSocket ++的行为类似于标准的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会完全停止事件的处理。这不会给当前操作(例如套接字关闭握手)提供完成的机会。它将使套接字处于悬空状态,这可能会导致操作系统级别的超时或其他错误。