概要
解析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
- 支持模型类型
总结
提示:这里可以添加总结
例如:
提供先进的推理,复杂的指令,更多的创造力。