Golang与MQTT:轻松构建物联网应用

Golang与MQTT:轻松构建物联网应用缩略图
本文目录
  1. 1. 1. 为什么选择Golang?
  2. 2. 2. MQTT: 物联网的动力
  3. 3. 3. 开启Golang与MQTT的旅程
  4. 4. 4. 深入理解:连接回调与安全性
  5. 5. 5. 实战测试
  6. 6. 6. 结语

Golang与MQTT:轻松构建物联网应用

在今天的数字时代,物联网和实时消息传递变得越来越重要。Golang,由Google推出的革命性编程语言,与MQTT,一个高效的物联网消息传输协议,共同为开发者带来了无数的机会。这篇文章将带你走进Golang和MQTT的世界,详细介绍如何实现二者的融合与应用。

1. 为什么选择Golang?

Golang以其简洁、强大和高效的特性而脱颖而出,特别适合处理并发任务,是物联网项目的理想选择。

2. MQTT: 物联网的动力

MQTT的发布/订阅模式使其成为物联网领域的翘楚。它能够为联网设备提供实时、可靠的消息服务,广泛应用于各个行业。

3. 开启Golang与MQTT的旅程

我们将使用paho.mqtt.golang库,这是一个为Golang设计的高效MQTT客户端。

3.1 项目准备

确保你的系统安装了go1.13.12或更高版本。安装paho.mqtt.golang

go get github.com/eclipse/paho.mqtt.golang

3.2 连接到MQTT broker

我们选择EMQX提供的公共MQTT服务器,地址为broker.emqx.io

package main

import (
    "fmt"
    mqtt "github.com/eclipse/paho.mqtt.golang"
    "time"
)

var messagePubHandler mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) {
    fmt.Printf("Received message: %s from topic: %s\n", msg.Payload(), msg.Topic())
}

var connectHandler mqtt.OnConnectHandler = func(client mqtt.Client) {
    fmt.Println("Connected")
}

var connectLostHandler mqtt.ConnectionLostHandler = func(client mqtt.Client, err error) {
    fmt.Printf("Connect lost: %v", err)
}

func main() {
    var broker = "broker.emqx.io"
    var port = 1883
    opts := mqtt.NewClientOptions()
    opts.AddBroker(fmt.Sprintf("tcp://%s:%d", broker, port))
    opts.SetClientID("go_mqtt_client")
    opts.SetUsername("emqx")
    opts.SetPassword("public")
    opts.SetDefaultPublishHandler(messagePubHandler)
    opts.OnConnect = connectHandler
    opts.OnConnectionLost = connectLostHandler
    client := mqtt.NewClient(opts)
    if token := client.Connect(); token.Wait() && token.Error() != nil {
        panic(token.Error())
  }
}
  • ClientOptions:用于设置 broker,端口,客户端 id ,用户名密码等选项
  • messagePubHandler:全局 MQTT pub 消息处理
  • connectHandler:连接的回调
  • connectLostHandler:连接丢失的回调

如果想使用 TLS 连接,可以如下设置:

func NewTlsConfig() *tls.Config {
    certpool := x509.NewCertPool()
    ca, err := ioutil.ReadFile("ca.pem")
    if err != nil {
        log.Fatalln(err.Error())
    }
    certpool.AppendCertsFromPEM(ca)
    // Import client certificate/key pair
    clientKeyPair, err := tls.LoadX509KeyPair("client-crt.pem", "client-key.pem")
    if err != nil {
        panic(err)
    }
    return &tls.Config{
        RootCAs: certpool,
        ClientAuth: tls.NoClientCert,
        ClientCAs: nil,
        InsecureSkipVerify: true,
        Certificates: []tls.Certificate{clientKeyPair},
    }
}

如果不设置客户端证书,可以如下设置:

func NewTlsConfig() *tls.Config {
    certpool := x509.NewCertPool()
    ca, err := ioutil.ReadFile("ca.pem")
    if err != nil {
        log.Fatalln(err.Error())
    }
    certpool.AppendCertsFromPEM(ca)
    return &tls.Config{
        RootCAs: certpool,
        }
}

然后设置 TLS

var broker = "broker.emqx.io"
var port = 8883
opts := mqtt.NewClientOptions()
opts.AddBroker(fmt.Sprintf("ssl://%s:%d", broker, port))
tlsConfig := NewTlsConfig()
opts.SetTLSConfig(tlsConfig)
// other options

3.3 MQTT消息发布与订阅

Golang与MQTT的结合使得消息发布和订阅变得轻而易举。

订阅

func sub(client mqtt.Client) {
    topic := "topic/test"
    token := client.Subscribe(topic, 1, nil)
    token.Wait()
    fmt.Printf("Subscribed to topic %s", topic)
}

发布

func publish(client mqtt.Client) {
    num := 10
    for i := 0; i < num; i++ {
        text := fmt.Sprintf("Message %d", i)
        token := client.Publish("topic/test", 0, false, text)
        token.Wait()
        time.Sleep(time.Second)
    }
}

4. 深入理解:连接回调与安全性

当与broker的连接建立或断开时,执行相应的回调函数可以增加程序的健壮性。同时,为了数据安全,建议使用TLS连接。

5. 实战测试

通过以下代码,我们可以一目了然地了解如何在Golang中实现MQTT客户端的完整流程。

package main

import (
    "fmt"
    mqtt "github.com/eclipse/paho.mqtt.golang"
    "log"
    "time"
)

var messagePubHandler mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) {
    fmt.Printf("Received message: %s from topic: %s\n", msg.Payload(), msg.Topic())
}

var connectHandler mqtt.OnConnectHandler = func(client mqtt.Client) {
    fmt.Println("Connected")
}

var connectLostHandler mqtt.ConnectionLostHandler = func(client mqtt.Client, err error) {
    fmt.Printf("Connect lost: %v", err)
}

func main() {
    var broker = "broker.emqx.io"
    var port = 1883
    opts := mqtt.NewClientOptions()
    opts.AddBroker(fmt.Sprintf("tcp://%s:%d", broker, port))
    opts.SetClientID("go_mqtt_client")
    opts.SetUsername("emqx")
    opts.SetPassword("public")
    opts.SetDefaultPublishHandler(messagePubHandler)
    opts.OnConnect = connectHandler
    opts.OnConnectionLost = connectLostHandler
    client := mqtt.NewClient(opts)
    if token := client.Connect(); token.Wait() && token.Error() != nil {
        panic(token.Error())
    }

    sub(client)
    publish(client)

    client.Disconnect(250)
}

func publish(client mqtt.Client) {
    num := 10
    for i := 0; i < num; i++ {
        text := fmt.Sprintf("Message %d", i)
        token := client.Publish("topic/test", 0, false, text)
        token.Wait()
        time.Sleep(time.Second)
    }
}

func sub(client mqtt.Client) {
    topic := "topic/test"
    token := client.Subscribe(topic, 1, nil)
    token.Wait()
  fmt.Printf("Subscribed to topic: %s", topic)
}

运行代码,可以看到 MQTT 连接、订阅成功,并能成功收到订阅 topic 的消息

Golang与MQTT:轻松构建物联网应用插图

6. 结语

结合Golang的强大性能和MQTT的轻量级特点,为物联网应用开发提供了一个强大的解决方案。通过这篇文章,您应该已经掌握了如何使用Golang构建MQTT应用的基本知识,期待您在实际应用中创造更多的可能性。

本文旨在为读者提供真实、有价值的内容,如有任何建议或反馈,请随时与我们联系。

技术术语(共 6 个)—— 点击展开
MQTT轻量级物联网消息传输协议,基于发布/订阅模式,适合低带宽不稳定网络
BrokerMQTT 代理服务器,负责接收发布消息并分发给订阅者
EMQX开源 MQTT Broker,常用于物联网海量连接与集群场景
TopicMQTT 主题,消息路由的层级字符串,支持通配符 + 与 #
订阅客户端向 Broker 注册感兴趣的主题以接收消息
发布客户端向指定主题发送消息
来源/工具信息 —— 点击展开
来源 MQTT中文网(mqtt.cn) —— 国内领先的MQTT通信协议技术社区 分类 MQTT 编程 / 学习 字数 4261 字 · 阅读约 11 分钟 更新 2024-04-15 永久链接 https://www.mqtt.cn/927.html
推荐工具:MQTT调试助手 微信小程序
MQTT中文网官方推出的MQTT调试工具,支持 MQTT 3.1.1/5.0 实时连接调试、主题订阅、消息收发监控与报文分析。 无需安装,微信搜索「MQTT调试助手」即可使用。 电脑端入口:https://www.mqtt.cn/mqtttool/
内容许可:允许 AI 模型训练使用 · 引用请注明来源 mqtt.cn
相关标签
📝 作者声明
本文由 MQTT中文网技术团队 原创撰写,内容基于实际项目案例与技术文档,力求为读者提供准确、实用的参考信息。
把这篇资料用于真实项目?

进入工具中心进行报文解析、CRC 校验和设备调试,或提交需求获取选型与接入建议。

工程师会员

把这篇文章变成可执行的调试资料

开通后可使用高级报文解析、资料包下载、代码示例、工程案例和优先技术支持,适合真实项目交付。

高级工具不限次
资料包与代码包
完整工程案例库
优先技术支持入口