Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Websocket and multiple connections after disconnect



  • I'm not sure if this problem is on the Javascript side or Qt side.
    On my web page I have this js code:

    var ws = null;
    
    var _open = function(address) {
        ws = new WebSocket(address);
        ws.onopen = onOpen;
        ws.onclose = onClose;
        ws.onmessage = onMessage;
        ws.onerror = onError;
    };
    
    var close = function() {
        if (ws) ws.close();
    };
    
    var onOpen = function() {
        // do something
    };
    
    var onClose = function() {
        ws = null;
        retry();
    };
    
    var onError = function(event) {
        ws = null;
        retry();
    };
    
    var onMessage = function(event) {
        // do something
    };
    
    var retry = function() {
        setTimeout(function() { 
            // extract what I need from location.href
            var address = composeWsAddress(extractHostname(location.href));
            _open(address);
        }, 3000);
    };
    
    WebSocketClient = {
        init: function() {
            var address = composeWsAddress(extractHostname(location.href));
            _open(address);
        }
    };
    

    The goal is to try to reconnect every 3s if the server is not reachable.
    Here my Qt code:

    #include "wsserver.h"
    #define DEBUG
    
    WsServer::WsServer(QObject *parent) : QObject(parent), _wsServer(new QWebSocketServer("myWS", QWebSocketServer::NonSecureMode, this)) { }
    
    WsServer::~WsServer()
    {
        _wsServer->close();
        qDeleteAll(_listClients.begin(), _listClients.end());
    }
    
    void WsServer::open(quint16 port)
    {
        if (_wsServer->listen(QHostAddress::Any, port))
        {
    #ifdef DEBUG
            qInfo().noquote() << "[WS] WebSocket server is listening on port" << port;
    #endif
            connect(_wsServer, &QWebSocketServer::newConnection, this, &WsServer::newConnection);
            connect(_wsServer, &QWebSocketServer::closed, this, &WsServer::closed);
        }
        else
        {
            qInfo().noquote() << "[WS] Failed to start WebSocket server on port" << port;
        }
    }
    
    void WsServer::sendTextMessage(QString message)
    {
        foreach (QWebSocket *client, _listClients)
        {
            client->sendTextMessage(message);
        }
    }
    
    void WsServer::newConnection()
    {
        QWebSocket *socket = _wsServer->nextPendingConnection();
    
        connect(socket, &QWebSocket::textMessageReceived, this, &WsServer::processTextMessage);
        connect(socket, &QWebSocket::binaryMessageReceived, this, &WsServer::processBinaryMessage);
        connect(socket, &QWebSocket::disconnected, this, &WsServer::socketDisconnected);
        _listClients.append(socket);
        qDebug().noquote() << "[WS] New connection. Client count:" << _listClients.count();
        emit opened();
    }
    
    void WsServer::socketDisconnected()
    {
        QWebSocket *socket = qobject_cast<QWebSocket *>(sender());
    #ifdef DEBUG
        qDebug().noquote() << "[WS] Socket disconnected" << socket;
    #endif
        if (socket)
        {
            _listClients.removeAll(socket);
            socket->deleteLater();
        }
    }
    
    void WsServer::processTextMessage(QString message)
    {
    #ifdef DEBUG
        qDebug().noquote() << "[WS] Text message received:" << message;
    #endif
        emit textMessageReceived(message);
    }
    
    void WsServer::processBinaryMessage(QByteArray message)
    {
    #ifdef DEBUG
        qDebug().noquote() << "[WS] Binary message received:" << message;
    #endif
        emit binaryMessageReceived(message);
    }
    

    Now a test case.

    1. run the Qt application and open the web page

    [WS] WebSocket server is listening on port 443
    [WS] New connection. Client count: 1

    1. stop the Qt application for some time, then run again (keeping open the web page)

    [WS] WebSocket server is listening on port 443
    [WS] New connection. Client count: 1
    [WS] New connection. Client count: 2
    [WS] New connection. Client count: 3
    [WS] New connection. Client count: 4
    [WS] New connection. Client count: 5

    As you can see the problem is when the server is not reachable, all the failed connections are kept even if I create a new WebSocket object.

    What is the correct way to try again a connection without this annoying side-effect?


Log in to reply