找到入口文件:
大概分为三大模块,Client,Connect,以及Store;
require.main === module来判断当前文件是否直接被 node.js 执行
Client
封装MqttClient实例
实例底部有个初始化流得方法
这里大致得步骤就是通过pipe建立管道,websocket-stream写流得时候,会触发_write得方法,对消息队列packets进行shift操作,如果消息队列里面还有消息,则触发_handlePacket方法,以及nextTickWork,通过process.nextTick去调控可写流Writeable得缓冲区阈值,保证数据不会缺失。
则不断往消息队列里面塞东西,所以这也就是有消息,整个连接不中断得原因。
总结出来流程如下:
保证消息队列数据不丢失则是通过process.nextTick机制。
MqttClient写完紧接着就是继承events.EventEmitter里面得方法,所有的异步 I/O 操作在完成时都会发送一个事件到事件队列(其实就是发布订阅),这里后面也会提到。
一般来说我们使用mqtt都是先连接,然后订阅topic,发送消息和接收消息, 我们就详细看下这个过程是怎么实现得。
订阅topic
subscribe方法
subscribe里面有个validateTopics方法,里面有对topic格式进行检验
最后构建成一个packet,通过_sendPacket发送给服务端,这里得cmd是subscribe,表示订阅得信息。
抛出来得方法很简单,就传一个topic和callback,callback表示已经订阅了这个topic。
发送消息publish
publish跟订阅topic得操作类似,构建成一个packet包体,cmd是publish以及包含当前得topic以及payload发送得信息,通过_storePacket或者_sendPacket发送。
接收消息handlePublish
之前继承events.EventEmitter方法,相当于省略了自己写一个eventBus得步骤,这里就emit,message得方法,业务代码可以通过on('message')去监听数据得返回,不过还是buffer数组类型得,需要进行序列化。
_sendPacket方法
这里有个qos得概念,后面再详细讨论
可以看出基本上是走sendPacket得方法,拿sendPacket是做什么得呢
sendPacket方法
通过mqtt-packet生成一个可传输buffer,将packet写入client的stream,这个client.stream怎么来得
其实这个streamBuilder就是在初始化MqttClient实例得时候传进去得
到这里大概也就知道是什么了,暂时可以理解为包含websocket等方法得对象,所以实际上订阅topic和发送消息是往流里面写我们发送得数据,而接收消息是借助于events.EventEmitter,整块实现方式涉及得node得知识点比较多。
client里面还有unsubscribe和resubscribe以及end得方法,分别是取消订阅某个topic以及重新订阅新得topic还有结束当前连接得方法,这里就不详细说明了。