【发布时间】:2021-06-03 08:00:16
【问题描述】:
当我只是运行一个程序来测试与 mqtt 代理的连接时,客户端总是会丢失。 这是我的代码
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\n", err)
}
var messageSubHandler mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) {
fmt.Printf("Sub message: %s from topic: %s\n", msg.Payload(), msg.Topic())
}
func main() {
opts := mqtt.NewClientOptions()
opts.AddBroker("tcp://broker.emqx.io:1883")
opts.SetClientID("go_mqtt_client")
opts.SetResumeSubs(true)
opts.SetAutoReconnect(true)
opts.SetOrderMatters(false)
opts.SetCleanSession(false)
// opts.SetTLSConfig()
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)
s := make(chan os.Signal, 1)
signal.Notify(s, syscall.SIGINT, syscall.SIGTERM, syscall.SIGKILL)
select {
case <-s:
glog.Infoln(`quit`)
glog.Flush()
}
}
func sub(client mqtt.Client) {
topic := "topic/test"
token := client.Subscribe(topic, 2, messageSubHandler)
token.Wait()
fmt.Printf("Subscribed to topic: %s\n", topic)
}
结果是
$ go run cmd/client/client.go
Connected
Subscribed to topic: topic/test
Connect lost: EOF
Connected
Connect lost: EOF
Connected
...
我知道这是因为 clientId。但是现在我只是运行一个叫go_mqtt_client的客户端,不知道是不是配置的原因。我遇到过两次这个问题。第一次我不记得发生了什么变化,它可以工作。但是第二次(现在),我无法修复它。
It just can work if I change the ClientId...
【问题讨论】:
-
MQTT 规范要求代理在另一个客户端使用相同的客户端 ID 连接时断开会话。鉴于
go_mqtt_client在他们的demo code 中使用,您发出的问题很可能只是由于其他人使用相同的ID 连接(并且可能在断开连接时自动重新连接);有什么理由不能使用不同的 ID? (即更改opts.SetClientID("go_mqtt_client"))。 -
当然我可以使用另一个 ClientID 来代替
go_mqtt_client。我只是想知道为什么它一直在重新连接(这个时候有人在用这个ID吗?) -
最有可能;由于
broker.emqx.io是免费的公共 MQTT 代理,因此无法确定。但是,鉴于go_mqtt_client在示例代码中用作客户端 ID,因此很有可能有人在使用它(或者可能在代理的集成测试中使用它)。 -
go_mqtt_client是否可能由于选项而被保存? -
不确定你的意思;客户端 ID 将是您设置的任何值(它不会存储在代码中以外的任何地方;代理将保留该客户端 ID 的会话记录,但这在这里并不真正相关)。