Deploying a Node.js server with WebSockets on a free hosting Heroku. Web- Desktop Clients (Qt)

Published December 17, 2021
Advertisement

Working example: https://mouse-click-js.herokuapp.com/ in which the coordinates of the mouse click are sent to the server and the response is returned to the client in the form of a message that it displays on the screen.

Instruction how to host on Heroku:

On the Heroku website, in the upper right corner, select "New" -> "Create new app":

6e285b7b-923e-4838-b06d-4174f19884e4-image.png

Type in the name of the game and select the region for the server and click the "Create app" button:

7053047e-b0a5-4cb1-b55b-8412e0a66a94-image.png

On the "Deploy" tab, click the "Connect to GitHub" button:

b0b053c2-30aa-4290-ba66-02c6b02d2e8a-image.png

A field will appear where you need to enter the name of the repository, click "Search":

ba0a6066-4d76-4449-9125-22d773984b33-image.png

A "Deploy Branch" button will appear, which downloads the application from GitHub, or you can click the "Enable Automatic Deploy" button, which will enable automatic download from GitHub whenever you do a "git push" on your computer.

The application will be deployed and you will have a link to the application.

Note. Free hosting on Heroku has limitations. For example, if the server has not been accessed for 30 minutes, then it goes to sleep. On the next call, the response will be received in 5-10 seconds, which is required to wake up the server. MySQL database has a 5 MB limit. Check out the Heroku website for other free account restrictions.

Server + web client sources in JavaScript: https://github.com/8Observer8/mouse-click-js

app.js

const express = require("express");
const http = require("http");
const ws = require("ws");
const path = require("path");

const app = express();
app.use(express.static(path.join(__dirname, "./public")));
app.get("/", (req, res) => { res.sendFile(path.join(__dirname, "index.html")) });

const httpServer = http.createServer(app);
const wss = new ws.Server({ server: httpServer });
wss.on("connection",
    (ws) =>
    {
        console.log("Client connected");
        ws.onmessage =
            (event) =>
            {
                const msg = JSON.parse(event.data);
                console.log(msg.x + ", " + msg.y);
                // Send an answer
                const resp = {
                    x: msg.x,
                    y: msg.y
                }
                ws.send(JSON.stringify(resp));
            }
    });

const port = process.env.PORT || 3000;
httpServer.listen(port, () => { console.log("Server started. Port: ", port); });

public/index.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Web Client</title>
</head>

<body>
    <h3>Click on the window.</h3>
    <div id="output" style="font-family: Arial; font-size: 14px;"></div>

    <script>
        const output = document.getElementById("output");
        output.innerHTML = "Wait for connection...";
        // const ws = new WebSocket("ws://localhost:3000");
        const ws = new WebSocket("wss://mouse-click-js.herokuapp.com");
        ws.onopen =
            () => {
                output.innerHTML = "Connected to the server";
                window.onclick = (event) => {
                    const x = event.clientX;
                    const y = event.clientY;
                    console.log(x + ", " + y)
                    ws.send(JSON.stringify({x: x, y: y}));
                };

                ws.onmessage = (event) => {
                    console.log(event.data);
                    const msg = JSON.parse(event.data);
                    output.innerHTML = `Answer from server: x = ${msg.x}, y = ${msg.y}`;
                }
            };
    </script>
</body>

</html>

package.json

{
  "name": "mouse-click-js",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node app.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.17.1",
    "ws": "^7.3.1"
  }
}

Client sources in Qt C++: https://github.com/8Observer8/MouseClick_QtClient_Qt5Cpp

main.cpp

#include <QtWidgets/QApplication>
#include <QtWidgets/QWidget>
#include <QtWidgets/QLabel>
#include <QtWidgets/QVBoxLayout>
#include <QtGui/QMouseEvent>
#include <QtWebSockets/QWebSocket>
#include <QtCore/QJsonDocument>
#include <QtCore/QJsonObject>
#include <QtCore/QDebug>

class Window : public QWidget {
    Q_OBJECT
private:
    QWebSocket m_webSocket;
    QLabel m_connection;
    QLabel m_output;
public:
    Window(QWidget *parent = nullptr) : QWidget(parent) {
        setWindowTitle("Qt C++ Client");
        resize(300, 300);
        QVBoxLayout *vbox = new QVBoxLayout(this);
        QLabel *instruction = new QLabel("Click on the window.");
        m_connection.setText("Wait for connection...");
        QFont font = QFont("Arial", 14);
        instruction->setFont(font);
        m_connection.setFont(font);
        m_output.setFont(font);
        vbox->addWidget(instruction);
        vbox->addWidget(&m_connection);
        vbox->addWidget(&m_output);
        vbox->addStretch(1);
        connect(&m_webSocket, &QWebSocket::connected,
                 this, &Window::onConnected);
        // m_webSocket.open(QUrl("ws://localhost:3000"));
        m_webSocket.open(QUrl("wss://mouse-click-js.herokuapp.com"));
    }
private slots:
    void onConnected() {
        m_connection.setText("Connected to server");
        connect(&m_webSocket, &QWebSocket::textMessageReceived,
                this, &Window::onMessageReceived);
    }
    void onMessageReceived(QString message) {
        qDebug() << message;
        QJsonDocument doc(QJsonDocument::fromJson(message.toUtf8()));
        QJsonObject data = doc.object();
        int x = data["x"].toInt();
        int y = data["y"].toInt();
        // Show data
        m_output.setText(QString("Answer from server: %1, %2").arg(x).arg(y));
    }
private:
    void mousePressEvent(QMouseEvent *event) override {
        Q_UNUSED(event);
        qDebug() << event->x() << " " << event->y();
        QJsonObject jsonObject;
        jsonObject["x"] = event->x();
        jsonObject["y"] = event->y();
        QString message = QJsonDocument(jsonObject).toJson(QJsonDocument::Compact);
        m_webSocket.sendTextMessage(message);
    }
};

#include "main.moc"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Window w;
    w.show();
    return a.exec();
}

MouseClick_QtClient_Qt5Cpp.pro

QT       += core gui websockets

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    main.cpp

HEADERS +=

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

0 likes 0 comments

Comments

Nobody has left a comment. You can be the first!
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Advertisement