许久不更新了,最近这段时间发生挺多事,说破了也就应届生那点破事,什么技术方向,等待offer,签约毁约的。最终还是老老实实回到公司继续实习,为了以后再拼搏一次吧。
最近公司做的项目中有用到消息推送,经过多方面的筛选之后确定了使用MQTT协议,相对于XMPP,MQTT更加轻量级,并且占用用户很少的带宽。MQTT是IBM推出的一种针对移动终端设备的基于TCP/IP的发布/预订协议,可以连接大量的远程传感器和控制设备。
长话短说,作为一名兢兢业业的实习生一直在为组里的大拿们提供各种服务,我们组的业务是围绕一个以MQTT协议进行Community Server 与Box的通信实现的,为了辅助我们团队在实体盒子数量有限或者环境受限制的情况下任然能进行各种消息的测试工作或者更新工作,我也就结合我们的业务用.net开发了一个基于MQTT通信的模拟工具。
一. 配置MQTT信息
MQTT的官网:http://mqtt.org/。其中http://mqtt.org/software里面提供了官方推荐的各种服务器和客户端使用的各种语言版本的API。
在VS工程中将MQTT相关类库导入后,根据官网的说明做好相关配置。注意的是有一些参数要根据自己的业务来配置。
例如这些:
private static int maxRetryCount ;
private static ushort sessionStatus ;
private static int retryCount ;
private static int reveive;
private static int receive ;
private static string MqttServer ;
private static int MqttPort ;
private static string MqttUserName ;
private static string MqttPassword ;
private static string MqttClientId ;
private static ushort MqttKeepAlivePeriod ;
private static string DefaultBoxId ;
private static string VersionNumber ;
private static MqttClient client ;
private static bool IsMQTTConnected ;
**需要注意的是:**
想要实现不同程序端的通信,MqttClientId 在不同的程序端注册连接的时候必须取不同的值,不然即便是不同的程序端在MQTT里代表的也是相同的云端或者相同的盒子,则不能实现相互通信。
二. 连接到MQTT
if (client == null) client = new MqttClient(MqttServer, MqttPort, false, null);
if (!IsMQTTConnected)
{
IsMQTTConnected = Connect();
RegisterEvents();
}
这里要注意的是:
RegisterEvents()即为注册的过程,然而在注册的时候会默认订阅所有消息,这就导致在后面要实现“订阅/发送”功能的时候会出现信息不对称的情况,即无论是否进行订阅操作只要MQTT收到任何消息发送请求,那么都会收到消息并作出反应,这样对于我要实现的一对一订阅/发送的目的造成了很大影响。
解决的办法是在各个项目订阅的同时标记上相关的全局变量,只有在Client_MqttMsgPublishReceived方法里检测到对应的全局变量才会对发送的消息进行反应。
连接函数connect()的核心代码:
client.Connect(clientId, user, password, false, keepAlivePeriod);
三. 订阅/发送
订阅:
client.Subscribe(new string[] { selTopic }, new byte[] { 1 });
其中selTopic是根据业务定制的订阅主题,是MQTT消息结构一个很重要的部分。
发送:
client.Publish(topic, payload, MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE, false);
四.事件相应的类库
public class MqttMsgPublishEventArgs : EventArgs
{
public MqttMsgPublishEventArgs(string topic, byte[] message, bool dupFlag, byte qosLevel, bool retain);
public bool DupFlag { get; set; }
public byte[] Message { get; }
public byte QosLevel { get; }
public bool Retain { get; }
public string Topic { get; }
}
我们一般根据自己的Topic和Message来对业务消息进行响应。即,MQTT只要收到消息,我们就可以获取以上结构里的消息信息。在代码的`private void Client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)函数中编写相应的响应代码即可。
五.总结
要做好一个MQTT的通信过程除了对整个通信流程有所了解,一定要清楚消息结构各个变量代表的含义,加以运用。