MQTT3.1.1 Golang源码分析

概要

解析MQTT 3.3.1的源码内容 ,如有错误,敬请指出
包地址 github.com/eclipse/paho.mqtt.golang

架构

在这里插入图片描述

通过golang实现的微服务完成对终端数据的采集,并利用MQTT详细完成消息的传递

解析

本文根据MQTT协议3.1.1进行展开探讨

1、MQTT的连接

首先,进行客户端参数的设置:url、客户端ID、handler以及保活时长等
① 通过包中options.go中的NewClientOptions()创建配置对象CLO,将所需的参数进行设定;
② 将配置的指针对象CLO传入包中的NewClient()函数中,以创建客户端连接;

func NewClient(o *ClientOptions) Client {
	c := &client{}
	c.options = *o
	if c.options.Store == nil {
		c.options.Store = NewMemoryStore()//初始化控制消息包持久化
	}
	switch c.options.ProtocolVersion {  //判断协议的版本,若没有指定,则默认先为4
	case 3, 4:                          //后期通过protocolVersionExplicit参数表明版本确定
		c.options.protocolVersionExplicit = true
	case 0x83, 0x84:
		c.options.protocolVersionExplicit = true
	default:
		c.options.ProtocolVersion = 4
		c.options.protocolVersionExplicit = false
	}
	c.persist = c.options.Store    //控制消息的持久化数据给到配置参数
	c.status = disconnected
	c.messageIds = messageIds{index: make(map[uint16]tokenCompletor)}
	c.msgRouter = newRouter()         //空链表
	c.msgRouter.setDefaultHandler(c.options.DefaultPublishHandler)  //设置回调
	c.obound = make(chan *PacketAndToken) //发布包通道参数
	c.oboundP = make(chan *PacketAndToken)  //其余包,如订阅包的通道参数
	return c   //返回一个待连接的客户端
}

③ 对客户端进行连接

func (c *client) Connect() Token {  //返回值为Token接口,该接口存在大量实现,如ConnectionToken(该Token连接专用)
	t := newToken(packets.Connect).(*ConnectToken)  //根据协议内容,连接包的协议标志为1
	DEBUG.Println(CLI, "Connect()")
	if c.options.ConnectRetry && atomic.LoadUint32(&c.status) != disconnected {  //允许重连且连接不是断开的
		// if in any state other than disconnected and ConnectRetry is
		// enabled then the connection will come up automatically
		// client can assume connection is up
		WARN.Println(CLI, "Connect() called but not disconnected")
		t.returnCode = packets.Accepted  //连接成功码
		t.flowComplete()  //token中的通道只是用来保证token的正常生成的,没有数据会发送到通道,只会默认关闭掉对应通道
		return t
	}
	c.persist.Open()  //持久化开启
	if c.options.ConnectRetry {
		c.reserveStoredPublishIDs() //存储发布消息,但前提是cleanSession标志位为0
	}
	c.setConnected(connecting)  //设置客户端的连接状态为正在连接
	go func() {
		if len(c.options.Servers) == 0 {
			t.setError(fmt.Errorf("no servers defined to connect to"))
			return
		}

	RETRYCONN:
		var conn net.Conn
		var rc byte
		var err error
		conn, rc, t.sessionPresent, err = c.attemptConnection()//1.1进行讨论,连接的核心思路
		if err != nil {
			if c.options.ConnectRetry {  //这里尝试重连,需要一定的线程休眠
				DEBUG.Println(CLI, "Connect failed, sleeping for", int(c.options.ConnectRetryInterval.Seconds()), "seconds and will then retry")
				time.Sleep(c.options.ConnectRetryInterval)

				if atomic.LoadUint32(&c.status) == connecting {
					goto RETRYCONN
				}
			}
			ERROR.Println(CLI, "Failed to connect to a broker") //如果没有重连设置,那么就生成连接错误码
			c.setConnected(disconnected)
			c.persist.Close()
			t.returnCode = rc
			t.setError(err)
			return
		}
		inboundFromStore := make(chan packets.ControlPacket)  //该通道的作用??
		if c.startCommsWorkers(conn, inboundFromStore) {  //1.2细节讨论该方法
			// Take care of any messages in the store
			if !c.options.CleanSession {  //清理标记位来决定
				c.resume(c.options.ResumeSubs, inboundFromStore)  //1.3
			} else {
				c.persist.Reset() //初始化操作,清空控制包中内容
			}
		} else {
			WARN.Println(CLI, "Connect() called but connection established in another goroutine")
		}

		close(inboundFromStore)  //关闭通道
		t.flowComplete()
		DEBUG.Println(CLI, "exit startClient")
	}()
	return t
}

例如:

  • Bert
  • GPT 初代
  • GPT-2
  • GPT-3
  • ChatGPT

技术细节

提示:这里可以添加技术细节

例如:

  • API
  • 支持模型类型

总结

提示:这里可以添加总结

例如:

提供先进的推理,复杂的指令,更多的创造力。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值