我正在使用webscokettpp c++客户端读取从web服务器发布的数据。我有一个带有测试按钮的c# 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;
}
}
我正试图找出一种方法来主要方法来c.run()当条件如果(pt.get("test") = "close")发生
当你使用客户端时,你需要在一个单独的线程上调用run();这将允许您在单独的线程上完成时优雅地停止客户端。IIRC然后run()将退出,这意味着您可以关闭线程并在需要时重新开始。
请参阅此常见问题解答,特别是"如何干净地退出基于Asio传输的程序";部分。停止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关闭握手等待。亚洲是异步的。当对上述方法(stop_listening, close等)的调用完成后,服务器仍然在监听,连接仍然是活动的,直到io_service绕过异步处理套接字和WebSocket协议关闭握手。当所有操作完成后,io_service::run方法将自动干净地退出。警告:Asio的io_service有一个叫做stop的方法。websocketpp::transport::asio::endpoint::stop包装这个方法。虽然这个操作的名字听起来很温和,但它是一个功能强大且具有破坏性的操作,只应该在特殊情况下使用。如果您没有很好的理由使用io_service::stop或endpoint::stop,那么您的程序很可能出现故障,并可能表现出不稳定的行为。具体来说,io_service::stop完全停止事件的处理。这不会给当前操作(如套接字关闭握手)完成的机会。它将使您的套接字处于悬空状态,可能会调用操作系统级超时或其他错误。