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:

(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);

Hi there,

I’m not sure I follow what your issue is here. Are you trying to resolve the QAbstractSocket::ConnectionRefusedError when making the WebSocket connection to your Render service?

I’m not sure why setting the user agent helps on Glitch, but from what I see in your code, it shouldn’t matter on Render.

Regards,

Keith
Render Support, UTC+10 :australia:

QAbstractSocket::ConnectionRefusedError was an error for Glitch. But Render has another error: QAbstractSocket::RemoteHostClosedError. If you say that User-Agent will not help to resolve the the problem with Render I have no idea what can I try. Maybe is Render not friendly to non-browser clients?

The solution to the problem on Glitch was possible thanks to wh0 who 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 code is in the first post of this topic. 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. 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();
}