Search code examples
javascriptnode.jsgoogle-app-enginewebsocketsocket.io

WebSocket connections failing on GCloud server


I'm running a Node server using Express and socket.io on Google Cloud. The page loads but the connection to the server gets refused immediately. I suspect I either have to configure my environment to allow a connection to that URL, which I'm sure on how to do, or I have to locally download socket.io.

server.js

const express = require("express");
const app = express();
const http = require("http");
const server = http.createServer(app);
const { Server } = require("socket.io");
const io = new Server(server);
const fs = require("fs");

async function getCount() {
    return new Promise((resolve, reject) => {
        fs.readFile("count.json", (err, data) => {
        if (err) {
            reject(err);
        } else {
            const count = JSON.parse(data).count;
            resolve(count);
        }
        });
    });
}

async function writeCount(count) {
    const data = {
        count: count
    };

    return new Promise((resolve, reject) => {
        fs.writeFile("count.json", JSON.stringify(data), (err) => {
        if (err) {
            reject(err);
        } else {
            resolve();
        }
        });
    });
}


app.use(express.static("public"));

io.on("connection", (socket) => {
    socket.on("error", console.error);

    getCount().then(count => {
        io.emit("init", count);
    }).catch(err => {
        console.log(err);
    })

    socket.on("serversync", (receivedSync) => {
        console.log("received " + receivedSync);
        if (receivedSync >= 120) {
            console.log("not using " + receivedSync);
            return;
        }
        
        getCount().then(count => {
            let total = count + parseInt(receivedSync);
            io.emit("clientsync", total);
            writeCount(total);
        }).catch(err => {
            console.log(err);
        })
    });
});

app.get("/init", (req, res) => {
    let files = fs.readdirSync("./public/audio");
    res.json([files]);
})

const PORT = process.env.PORT || 8080;

server.listen(PORT, () => {
    console.log(`Listening on port ${PORT}.`);
});

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <script src="https://code.jquery.com/jquery-3.6.0.min.js" crossorigin="anonymous"></script>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Kalam:wght@700&display=swap" rel="stylesheet">
    <script src="https://cdn.socket.io/4.5.4/socket.io.min.js"></script>
    <link rel="stylesheet" href="css/index.css">
  </head>
  <body class="center">
    <div>
      <h1 id="global"></h1>
      <h2 id="globalText">Global Pikas</h2>
    </div>

    <div>
      <img id="buttonImg" src="images/button.gif" alt="Pika" onclick="onClick()">
    </div>  

    <div id="counterDiv">
      <h3 id="counter">0</h3>
      <h4 id="counterText">Times Pika'd</h4>
    </div>

    <script src="js/index.js"></script>
    <script src="js/animator.js"></script>
  </body>
</html>

Errors


Solution

    1. Websockets isn't available on GAE standard. It's only available on Flexible env (see documentation).

    2. See sample code from Google for using sockets.io