Search code examples
javascriptreactjswebsocketmqttmosquitto

MQTT.js unable to make localhost broker connection


I work on a React Native mobile app. I use MQTT.js to establish connection with a broker. As a first test I made a connection with the Mosquitto public broker. I managed to connect only the WebSockets ports (8080 & 8081). Unfortunately the connection with my localhost Mosquitto broker failed without error.

First of all I installed Mosquitto and Node-RED on my Linux computer. I started both with respectively $ mosquitto -v and $ node-red. On Node-RED I created my first flow : a inject node connected to a mqtt publisher and a mqtt subscriber connected to debug node. The mqtt publisher and subscriber was on the same topic and was successfully connected to my Mosquitto localhost broker. I deployed : It works.

If I try a connection with my React app :

let mqtt = require('mqtt')
let client = mqtt.connect('mqtt://localhost:1883')
console.log('client', client)

client.on('connect', function () {
    console.log('connected')
})

client.on('error', function (error) {
    console.log('error', error)
})

It run but my Mosquitto broker doesn't receive any new connection. console.log('client', client) return this :

'client', 
 { options: 
   { protocol: 'ws',
     slashes: true,
     auth: null,
     host: 'localhost:1883',
     port: 1883,
     ...
   }
}

protocol: 'ws' stand for WebSockets, but my Mosquitto broker is on IP protocol, so I create a protocol.conf in /etc/mosquitto/conf.d folder and write the line protocol websockets. Then when I restart Mosquitto $ mosquitto -v -c /etc/mosquitto/conf.d/protocol.conf it show :

mosquitto version 1.6.4 starting
Config loaded from /etc/mosquitto/conf.d/protocol.conf.
Opening websockets listen socket on port 1883.

I re-compile my React app : doesn't work.

Unless console.log('client', client) my log is empty, any errors.

I expect at least a connection error, but even Mosquitto broker doesn't receive attempt of connection.


Solution

  • localhost means self - the computer that's executing the code that references localhost. Inside a React app, that's going to be the computer that's running the web browser that's loading the React app, which I'm betting is not the computer that's running your Mosquitto broker.

    You need to find out the IP address of the computer that's running the broker and use it instead of localhost. That won't be that 127.0.0.1, which is the IP address for localhost, means the same thing and would have the same problem. It will probably look like 10.0.x.x or 192.168.x.x.

    You should also not use port 1883 for MQTT over web sockets. It can work, but 1883 is the default MQTT over TCP port. If you haven't changed the default configuration of Mosquitto it will already be listening on port 1883. Port 8883 is often used for MQTT over web sockets - the exact port number doesn't matter as much as making sure it's not already in use. It's probably working right now because you only added the protocol websockets line. If you're never going to use the broker for anything other than websockets then you can safely ignore this part, but if you'll ever want something to connect to it using MQTT over TCP, websockets on port 1883 will become quickly confusing.

    Edit @hardlib had a great suggestion, pointing out that if the web page is served by the same computer as the MQTT broker is running on you can use a call to location.host to get the name or IP address of the server/broker.