The idea: store an initial port in a local config.json. Each startup tries to bind the WebSocket server; if the port is occupied, increment the port in config.json, save, relaunch Electron until a free port is found.

Example config:

{"port":1081}

Code snippet:

const { app, BrowserWindow, dialog } = require("electron");
const WebSocket = require("ws");
const fs = require("fs");
let wss = {};
openWs();
function openWs() {
fs.readFile("config.json", "utf-8", (err, configFileDataRes) => {
if (err) {
dialog.showMessageBox({
type: "info",
title: "Read config failed",
message: "Please reinstall",
detail: JSON.stringify(err),
});
throw err;
}
const configFileData = JSON.parse(configFileDataRes);
try {
wss = new WebSocket.Server({ port: configFileData.port });
} catch (error) {
console.log("Create WebSocket failed:", error);
}
wss.on("connection", (ws) => {
console.log(configFileData.port + " connected");
ws.on("message", (message) => {
message = JSON.parse(message);
if (message.type == "open_page") {
const win = new BrowserWindow();
win.loadFile(message.src);
win.webContents.openDevTools({ mode: "detach" });
if (message.big) win.maximize();
}
});
ws.send("ok");
});
wss.on("error", () => {
storeData({ port: parseInt(configFileData.port) + 1 }, "config.json");
app.exit();
app.relaunch();
});
});
}