【问题标题】:Cannot connect to Eclipse Mosquitto broker using Node.js mqtt library无法使用 Node.js mqtt 库连接到 Eclipse Mosquitto 代理
【发布时间】:2020-06-01 17:09:21
【问题描述】:

我在 172.17.0.2:1883 上的本地 docker 容器上运行 Eclipse Mosquitto

我可以使用 MQTT.fx 客户端发布/订阅,但现在尝试从节点连接到代理但无法连接。

主题是“传感器”

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                            NAMES
e747c86b6ec1        eclipse-mosquitto   "/docker-entrypoint.…"   5 hours ago         Up 5 hours          0.0.0.0:1883->1883/tcp, 0.0.0.0:9001->9001/tcp   adoring_varahamihira

当我检查 IP 地址时

docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' e747c86b6ec1
172.17.0.2

我正在尝试使用以下节点服务器连接到我的 MQTT 代理,但“连接”事件似乎从未发生过。

// Note: I have an express server running but didn't include 
const mqtt = require("mqtt")

var MQTT_TOPIC = "sensors";
var MQTT_ADDR = "mqtt://172.17.0.2";
var MQTT_PORT = 1883;

var client = mqtt.connect(MQTT_ADDR, {
  port: MQTT_PORT,
  clientId: 'bgtestnodejs232323',
  protocolId: 'MQIsdp',
  protocolVersion: 3,
  connectTimeout: 1000,
  debug: true
});

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

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

当我跑步时:

console.log(util.inspect(client))

输出是:

MqttClient {
  options:
   { protocol: 'mqtt',
     slashes: true,
     auth: null,
     host: '172.17.0.2',
     port: 1883,
     hostname: '172.17.0.2',
     hash: null,
     search: null,
     query: [Object: null prototype] {},
     pathname: null,
     path: null,
     href: 'mqtt://172.17.0.2',
     clientId: 'bgtestnodejs232323',
     protocolId: 'MQIsdp',
     protocolVersion: 3,
     connectTimeout: 1000,
     debug: true,
     defaultProtocol: 'mqtt',
     keepalive: 60,
     reschedulePings: true,
     reconnectPeriod: 1000,
     clean: true,
     resubscribe: true,
     customHandleAcks: [Function] },
  streamBuilder: [Function: wrapper],
  outgoingStore: Store { options: { clean: true }, _inflights: Map {} },
  incomingStore: Store { options: { clean: true }, _inflights: Map {} },
  queueQoSZero: true,
  _resubscribeTopics: {},
  messageIdToTopic: {},
  pingTimer: null,
  connected: false,
  disconnecting: false,
  queue: [],
  connackTimer:
   Timeout {
     _called: false,
     _idleTimeout: 1000,
     _idlePrev: [TimersList],
     _idleNext: [TimersList],
     _idleStart: 478,
     _onTimeout: [Function],
     _timerArgs: undefined,
     _repeat: null,
     _destroyed: false,
     [Symbol(unrefed)]: false,
     [Symbol(asyncId)]: 9,
     [Symbol(triggerId)]: 1 },
  reconnectTimer: null,
  _storeProcessing: false,
  _packetIdsDuringStoreProcessing: {},
  nextId: 26898,
  outgoing: {},
  _firstConnection: true,
  _events:
   [Object: null prototype] {
     close: [ [Function], [Function], [Function] ],
     connect: [Function] },
  _eventsCount: 2,
  _maxListeners: undefined,
  stream:
   Socket {
     connecting: true,
     _hadError: false,
     _handle:
      TCP {
        reading: false,
        onread: [Function: onStreamRead],
        onconnection: null,
        [Symbol(owner)]: [Circular] },
     _parent: null,
     _host: null,
     _readableState:
      ReadableState {
        objectMode: false,
        highWaterMark: 16384,
        buffer: BufferList { head: null, tail: null, length: 0 },
        length: 0,
        pipes: [Writable],
        pipesCount: 1,
        flowing: true,
        ended: false,
        endEmitted: false,
        reading: false,
        sync: true,
        needReadable: false,
        emittedReadable: false,
        readableListening: false,
        resumeScheduled: true,
        paused: false,
        emitClose: false,
        destroyed: false,
        defaultEncoding: 'utf8',
        awaitDrain: 0,
        readingMore: false,
        decoder: null,
        encoding: null },
     readable: false,
     _events:
      [Object: null prototype] {
        end: [Array],
        data: [Function: ondata],
        error: [Function: nop],
        close: [Function] },
     _eventsCount: 4,
     _maxListeners: 1000,
     _writableState:
      WritableState {
        objectMode: false,
        highWaterMark: 16384,
        finalCalled: false,
        needDrain: false,
        ending: false,
        ended: false,
        finished: false,
        destroyed: false,
        decodeStrings: false,
        defaultEncoding: 'utf8',
        length: 34,
        writing: false,
        corked: 1,
        sync: true,
        bufferProcessing: false,
        onwrite: [Function: bound onwrite],
        writecb: null,
        writelen: 0,
        bufferedRequest: [Object],
        lastBufferedRequest: [Object],
        pendingcb: 9,
        prefinished: false,
        errorEmitted: false,
        emitClose: false,
        bufferedRequestCount: 9,
        corkedRequestsFree: [Object] },
     writable: true,
     allowHalfOpen: false,
     _sockname: null,
     _pendingData: null,
     _pendingEncoding: '',
     server: null,
     _server: null,
     [Symbol(asyncId)]: 5,
     [Symbol(lastWriteQueueSize)]: 0,
     [Symbol(timeout)]: null,
     [Symbol(kBytesRead)]: 0,
     [Symbol(kBytesWritten)]: 0 } }

我一直在尝试这个答案中的建议:Why is MQTT not connecting with NodeJS?

感谢您的帮助!

【问题讨论】:

  • 注意到您在 1883 上运行代理,但我再次看到您在代码中使用 9001。 9001 是正确的端口吗?
  • 抱歉,这是我的错误 - 我正在试验 9001。它不适用于 9001 或 1883。我会将问题编辑为 1883 和适当的输出。
  • nodejs 代码在哪里运行(docker 主机,或者在同一主机上的另一个容器中)?还要添加一个client.on('error', function(err){}) 回调,以便您查看客户端未连接的原因。
  • Nodejs 代码在本地主机上运行。我的代码中确实有错误处理程序,但它没有触发(我在上面编辑了它)。再次感谢
  • 本地主机是指托管 docker 引擎的机器?

标签: node.js docker mqtt mosquitto


【解决方案1】:

由 Docker 引擎分发给 Docker 容器的 IP 地址范围 172.17.0.0/16 是供私人使用的 RFC1918 集的一部分。

对于 Docker,它们用于内部“桥接”网络,并且只能从其他 docker 容器或托管 Docker 引擎的机器访问。

您的 mosquitto 容器信息的 0.0.0.0:1883->1883/tcp, 0.0.0.0:9001->9001/tcp 输出显示这些端口已暴露并映射到主机 IP 地址。如果您将 172.17.0.2 更改为托管 Docker 引擎的机器的 IP 地址,您应该能够连接。

【讨论】:

  • 我将它设置为MQTT_ADDR = "mqtt://188.XXX.XXX.XX.";我本地机器的IP地址,但仍然没有错误或连接。我认为您的 docker 点可能是问题所在,也许我应该尝试在 docker 容器中运行我的节点服务器?再次感谢!
  • 你还没有回答这个问题,是不是所有东西都在同一台机器上运行,nodejs 和 docker 容器?
  • 抱歉!是的,都在同一台机器上
  • 谢谢你帮我解决了这个问题。我能够通过在 docker 容器中运行我的节点服务器来解决这个问题。然后我能够连接到 172.17.0.2。我将这篇文章用于 Dockerfile 和 nodejs 文件的骨架。 study.ar-leung.net/node-js-mqtt-docker我使用的命令是`docker run -it -p 9002:3002 -v $(pwd):/app mqtt-server /bin/bash`然后运行`node app/mqtt-server.js`跨度>
【解决方案2】:
  • 9001 端口是 websocket 监听器
  • 端口 1883 是本机 MQTT 侦听器

您正在为您的代理 URL 使用 mqtt:// 架构,该架构指示本机 MQTT 协议,但您正在强制使用端口 9001。

如果您想使用 WebSockets,那么您应该将架构更改为 ws://

如果您想使用原生 MQTT,则需要将端口更改为 1883

【讨论】:

  • 谢谢,这是我的错误,应该是 1883,但它仍然不起作用。我已经用客户端对象的端口控制台日志更新了这个问题。感谢您的解释,它确实有助于我理解默认端口。