Failed to retrieve data with Qt from deployed Node.js server using WebSockets
-
I wrote a simple server example in JavaScript that sends some data to a client when the client connects: send-gravity-from-server-to-client-box2d-wasm-js
I deployed this simple server on free hostings: https://glitch.com/ and https://render.com/. Web clients work well:
- Glitch: https://merciful-regal-soursop.glitch.me
- Render: https://send-gravity-box2d-wasm-js.onrender.com
(It takes 15-20 seconds for Glitch and 50 seconds for Render to wake up the server)
I try to connect to the server from Qt and show received data:
Widget::Widget(QWidget *parent) : QWidget(parent) { connect(&m_webSocket, &QWebSocket::connected, this, &Widget::onConnected); connect(&m_webSocket, &QWebSocket::textMessageReceived, this, &Widget::onMessageReceived); connect(&m_webSocket, &QWebSocket::errorOccurred, this, &Widget::errorOccurred); // QUrl url("wss://send-gravity-box2d-wasm-js.onrender.com"); QUrl url("wss://merciful-regal-soursop.glitch.me"); m_webSocket.open(url); } Widget::~Widget() {} void Widget::onConnected() { qDebug() << "connected"; } void Widget::onMessageReceived(const QString &message) { qDebug() << message; } void Widget::errorOccurred(QAbstractSocket::SocketError error) { qDebug() << error; }
I see:
connected QAbstractSocket::RemoteHostClosedError QAbstractSocket::RemoteHostClosedError
in the Qt Debug console when I try to connect to Render and I see
QAbstractSocket::ConnectionRefusedError
when I try to connect to Glitch. -
To solve this problem on Glitch (I haven't tested it on Render yet), you need to find out the
User-Agent
in the web client like this:console.log(window.navigator.userAgent);
Copy and paste the resulting string value above into the second argument of the
setRawHeader()
method:QUrl url("wss://merciful-regal-soursop.glitch.me"); QNetworkRequest request; request.setUrl(url); request.setRawHeader(QByteArray("User-Agent"), QByteArray("Mozilla/5.0 " "(Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/124.0.0.0 Safari/537.36")); m_webSocket.open(request);
The solution to the problem on Glitch was possible thanks to wh0 helped me here:
do you know if this sends a User-Agent header? Glitch requires one to be present. my searching shows that QWebSocket has an
open
method that takes a network request QWebSocket Class | Qt WebSockets 6.7.1. try using that -
I have created duplicates on another forums:
-
To solve this problem on Glitch (I haven't tested it on Render yet), you need to find out the
User-Agent
in the web client like this:console.log(window.navigator.userAgent);
Copy and paste the resulting string value above into the second argument of the
setRawHeader()
method:QUrl url("wss://merciful-regal-soursop.glitch.me"); QNetworkRequest request; request.setUrl(url); request.setRawHeader(QByteArray("User-Agent"), QByteArray("Mozilla/5.0 " "(Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/124.0.0.0 Safari/537.36")); m_webSocket.open(request);
The solution to the problem on Glitch was possible thanks to wh0 helped me here:
do you know if this sends a User-Agent header? Glitch requires one to be present. my searching shows that QWebSocket has an
open
method that takes a network request QWebSocket Class | Qt WebSockets 6.7.1. try using that -
-
My following Qt 6.6.3 example works on Android, Desktop, and Web (with Qt WebAssembly). It prints data received from the server. The server contains the Box2D-WASM library. It sends the gravity value in JSON format when a client is connected. It is useful example to make multiplayer games with physics on the server side. I have deployed the example on free Glitch hosting: https://glitch.com/edit/#!/merciful-regal-soursop from the GitHub repository: send-gravity-from-server-to-client-box2d-wasm-js The client contains only one
main.cpp
file. It outputs the following information to the console:connected "{\"action\":\"scGravity\",\"data\":\"{\\\"x\\\":0,\\\"y\\\":-3}\"}"
You should download OpenSSL to run the following example on Android. Open the following window in Qt Creator (
Edit
>Preferences...
>Devices
>Android
):Add the following path to your pro-file:
QT += core gui websockets widgets android: include(C:/Qt/Tools/OpenSSL-1.1.1j/Win_x64/bin/openssl.pri) CONFIG += c++17 SOURCES += \ main.cpp
Read how to add OpenSSL to your CMake project if you use CMake instead of QMake in the Qt documentaion: Adding OpenSSL Support for Android
Build the following example for Android, Desktop, and WebAssembly (I have tested it):
main.cpp
#include <QtNetwork/QNetworkRequest> #include <QtWebSockets/QWebSocket> #include <QtWidgets/QApplication> #include <QtWidgets/QWidget> class Widget : public QWidget { Q_OBJECT public: Widget() { setWindowTitle("Show gravity from server with Box2D-WASM"); resize(420, 200); connect(&m_webSocket, &QWebSocket::connected, this, &Widget::onConnected); connect(&m_webSocket, &QWebSocket::textMessageReceived, this, &Widget::onMessageReceived); connect(&m_webSocket, &QWebSocket::errorOccurred, this, &Widget::onErrorOccurred); QUrl url("wss://merciful-regal-soursop.glitch.me"); QNetworkRequest request; request.setUrl(url); request.setRawHeader(QByteArray("User-Agent"), QByteArray("Mozilla/5.0 " "(Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/124.0.0.0 Safari/537.36")); m_webSocket.open(request); } ~Widget() {} private slots: void onConnected() { qDebug() << "connected"; } void onMessageReceived(const QString &message) { qDebug() << message; } void onErrorOccurred(QAbstractSocket::SocketError error) { qDebug() << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"; qDebug() << "Error:" << error; qDebug() << "Device supports OpenSSL:" << QSslSocket::supportsSsl(); qDebug() << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"; } private: QWebSocket m_webSocket; }; #include "main.moc" int main(int argc, char *argv[]) { QApplication app(argc, argv); Widget w; w.show(); return app.exec(); }
-