从 C# UI 应用程序关闭阻止 webscokettpp 客户端的客户端连接
Posted
技术标签:
【中文标题】从 C# UI 应用程序关闭阻止 webscokettpp 客户端的客户端连接【英文标题】:Close blocking client connection of webscokettpp client from C# UI application 【发布时间】:2016-10-06 21:43:22 【问题描述】:我正在使用 webscokettpp c++ 客户端来读取从网络服务器发布的数据。我有一个带有测试按钮的 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;
当条件 if(pt.get("test") = "close" ) 发生时,我正在尝试找出一种从 c.run() 中退出的 main 方法。
【问题讨论】:
我猜 echo_client 是为 echo_server 而不是任何网络服务器工作的。 错误,break
? return
?
【参考方案1】:
您需要在使用客户端时在单独的线程上调用 run();然后,当您在单独的线程上完成时,这将允许您优雅地停止客户端。 IIRC 然后 run() 将退出,这意味着您可以关闭线程并在需要时重新开始。
请参阅this FAQ,尤其是“我如何干净地退出基于 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 完全停止事件的处理。这不会给当前操作(例如套接字关闭握手)提供完成的机会。它将使您的套接字处于悬空状态,这可能会引发操作系统级别的超时或其他错误。
【讨论】:
以上是关于从 C# UI 应用程序关闭阻止 webscokettpp 客户端的客户端连接的主要内容,如果未能解决你的问题,请参考以下文章
JetBrains Rider C# | Windows 窗体 UI [关闭]