Cannot connect websockets when target is e.g. 'ws://localhost:3050'

I am currently working on a project where I want to allow a client, e.g. a smartphone on the local network, to connect to the balena host, in this case a Raspberry Pi 3B+, run a set of commands, and close the local connection.

Using a NodeJS image, I am currently doing this using the Websocket library.

Say I want to connect through port 3000, I am perfectly able to do this when I know the local IP address obtained in the dashboard - but am not able to connect over localhost:3050.

Just being able to use localhost simplifies the process quite a bit. Any insights?

All the best, and thank you,
Rasmus

Hi @rasmus,

Can you please post some code? Like the Dockerfile/docker-compose.yml file?
Because you’re trying to connect to the NodeJS websocket via the local.ip:3000, but localhost:3050 does not work.

My first question is: you’re trying to connect to port 3000 and then 3050, why all of a sudden 3050?
And my second question: Who wants to connect to localhost:3050, another docker container? Or the same docker container, so the NodeJS who starts the server is also a client? Or some other PC on the same network?

I’ve quite some experience with NodeJS and sockets, so I think I’ll be able to help you with some further details!

Thank you very much for replying!

My mistake, I meant 3050 all along, not 3000. It is a PC/smartphone on the same network that wants to connect.

The dockerfile is very basic, but I have attached it here, alongside the server side code:

Typescript server-side code snippet:

// trigger event when connection is up
socket.on("connection", (ws: WebSocket) => {
  ws.onmessage = event => {
    const payload: WebSocket.Data = event.data;

    ws.send(`Hello, you sent -> ${payload}`);
    console.log(payload);

    switch (payload) {
      case "startSensorPairing": {
        console.log("Running start function");
        return;
      }
      case "startCalibration": {
        console.log("Running calibration function");
        return;
      }
    }
  };

  // send immediatly a feedback to the incoming connection
  ws.send("Hi there, I am a WebSocket server");
});

server.listen(process.env.PORT || port, () => {
  console.log("Server online");
});

Docker file:

# base-image for node on raspberrypi3
# see more about dockerfile templates here: https://www.balena.io/docs/learn/develop/dockerfile/#dockerfile-templates
# and about resin base images here: https://www.balena.io/docs/reference/base-images/base-images/
# Note the node:slim image doesn't have node-gyp
FROM resin/raspberrypi3-node:8.0.0

# Enable systemd init system in container
ENV INITSYSTEM on

RUN apt-get update && apt-get install -y \
    build-essential -y \
    bluetooth \
    bluez \
    libbluetooth-dev \
    libudev-dev \
    rm -rf /var/lib/apt/lists/*

RUN npm install noble
RUN npm install express
RUN npm install ws

# Defines our working directory in container
WORKDIR /usr/src/app

# Copies the package.json first for better cache on later pushes
COPY package.json package.json

# This will copy all files in our root to the working directory in the container
COPY . ./

# server.js will run when container starts up on the device
CMD ["npm", "start"]

Hi @rasmus,

Thanks for some extra explanation.
So port 3050 is used, that’s fine, but I wasn’t sure if that was the problem.

If you want to connect from your PC to the Raspberry Pi, than you need the local IP address of that Raspberry Pi. If you connect to localhost:3050 from your PC, your PC is trying to connect to itself on port 3050. That’s the use of localhost.

Your code looks fine. Is it correct that you can connect with the Raspberry Pi if you use the local IP address of your Raspberry Pi right (Like 192.168.X.X:3050)? Because otherwise, you’ll need to open the ports from Docker. Like this. But in BalenaOS, this is done automatically for single docker containers (Correct me if I’m wrong).

So if what’s you’re trying to do is connect to the Raspberry Pi with “localhost:3050”, that’s not possible. You can use the hostname of the Raspberry Pi. You can find the hostname by ssh’ing into the machine and simply type: hostname. Then, you can use that hostname to connect from the PC to the Raspberry Pi like this: hostname.local:3050.

If something else is failing or this is not the answer you’re looking for, I’m pleased to answer your other questions! But share as much as possible, so that I, and others, can help you!

1 Like

Haha, sh*t, I really brainfarted here, as local hostname was exactly what I was looking for. Having previously used localhost between different processes on the same RPi, I confused the two. Thanks!