【发布时间】:2018-11-22 14:54:25
【问题描述】:
我正在开发一个小型系统,它由多个客户端和一个管理应用程序组成。每个客户端都有一个 QWebSocket 服务器来监听管理员的请求,因此管理员应用需要连接到不同的客户端。
这是我的登录对话框:
在登录之前,我不知道哪个是客户端 IP 地址,因此每次发送登录凭据时,我都需要尝试打开与该 IP 地址的连接。问题是在 Windows UI 中阻塞直到套接字服务器响应或超时,但在 Windows 中它工作正常。
编辑 1: 我遵循了Tung Le Thanh 的建议,因此代码中包含了他的提示。现在主要的问题是ConnectionHelper 不能在没有得到QSocketNotifier 的情况下发出任何信号:不能从另一个线程启用或禁用套接字通知器
我有一个 ConnectionHelper 负责向 WebSocket setver 发送接收数据。
main.cpp
ConnectionHelper *helper = new ConnectionHelper();
LoginDialog dialog(helper);
QThread* thread = new QThread();
helper->moveToThread(thread);
thread->start();
dialog.show();
return a.exec();
LoginDialog 的构造函数:
connect(helper, &ConnectionHelper::onConnectionError, this, &LoginDialog::onCxnError);
connect(helper, &ConnectionHelper::loginInformationReceived, this, &LoginDialog::onLoginInfo);
connect(helper, &ConnectionHelper::cxnEstablished, this, &LoginDialog::onConnected);
已接受的位置:
void LoginDialog::on_buttonBox_accepted()
{
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
QString host = ui->lineEditServer->text();
QString port = ui->lineEditPort->text();
QString ws = "ws://" + host + ":" + port;
helper->setUrl(QUrl(ws));
}
void ConnectionHelper::setUrl(QUrl url)
{
if(!webSocket)
{
webSocket = new QWebSocket();
connect(webSocket, &QWebSocket::textMessageReceived, this, &ConnectionHelper::processTextMessage, Qt::QueuedConnection);
connect(webSocket, &QWebSocket::binaryMessageReceived, this, &ConnectionHelper::processBinaryMessage);
connect(webSocket, &QWebSocket::disconnected , this, &ConnectionHelper::socketDisconnected);
connect(webSocket, QOverload<QAbstractSocket::SocketError>::of(&QWebSocket::error)
, this, [this](QAbstractSocket::SocketError error){
Q_UNUSED(error)
emit onConnectionError();
});
connect(webSocket, &QWebSocket::connected, this, [=]() {
emit cxnEstablished();
});
}
webSocket->open(url);
webSocket->open(url);
}
void ConnectionHelper::processTextMessage(QString message)
{
QJsonDocument response = QJsonDocument::fromJson(message.toUtf8());
QJsonObject objResponse = response.object();
QString action = objResponse[ACTION_KEY].toString();
if (action == ACTION_LOGIN)
emit loginInformationReceived(objResponse);
}
在收到任何响应之前,我会禁用“确定”按钮,并且在 Linux 上可以正常工作,但在 Windows 中,整个 UI 会阻塞并且在收到响应之前变得无响应。
我也尝试将ConnectionHelper 实例移动到另一个线程,但我得到了这样的响应:QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread
我没有想法,我需要找到一种方法使 webSocket->open(url) 异步或任何类似的东西。
谢谢。
【问题讨论】:
-
您好,不确定这是否有帮助,但您是否尝试过
QCoreApplication::processEvents()? -
您好,您可以在 lambda 中捕获
this并使用emit this->cxnEstablished();来查看它是否有效。请注意,setUrl 必须以 invokeMethod 形式调用,而不是从 UI 线程调用。 -
没用...是的,我使用你的建议
QMetaObject::invokeMethod( helper, "setUrl", Qt::QueuedConnection, Q_ARG(QUrl, QUrl(ws))
标签: c++ qt qtwebsockets