基于 Dotnetty 的 Mqtt Client

Dotnetty

    Netty是顶顶大名的网络通讯开发库,使通讯开发人员再也不用费九牛二虎之力来处理socket通讯和一些常见应用层协议如HTTP、WEBSOCKET、MQTT等底层问题,而可以专心做应用层的开发工作。Dotnetty是Azure团队照着Netty开发的C#版本。

MQTT Client

    基于 Netty/Dotnetty 提供的是MQTT 14种Packet和编码、解码的实现,但没有提供MQTT客户端或服务端的官方实现。我重点参考了https://github.com/jetlinks/netty-mqtt-client的java代码,其中包含了重连和重传机制,相较于其他netty的mqtt client更为成熟,但代码中出现的Future/Promise也着实不好对付。

JAVA到C#

    Java中的Future相当于C#的Task,Promise相当于TaskCompletionSource,后者主要用于将多个步骤合并为一个任务,都完成后再返回。Mqtt协议里,这种多步一回合的情况是普遍的,包括:

  • CONNECT——CONACT
  • PUBLISH——PUBACK
  • PUBLISH——PUBREC——PUBREL——PUBCOMP
  • SUBSCRIBE——SUBACK
  • UNSUBSCRIBE——UNSUBACK

   例如,Client对外提供的 Publish 方法在QoS>0的情况下,并不是WriteAndFlush后就算完成了,还要等到PUBACK(QoS=1)甚至PUBREL(QoS=2)才能返回,这中间Mqtt Client和Mqtt Broker之间已经进行了好几次通讯,因此需要用Promise/TaskCompletionSource来将这几步通讯包裹成一个任务,执行完后Publish方法才返回。

代码结构

    相关的代码已上传github,csdn下载,核心是MqttClient类,提供了Connect, Disconnect, Publish,Subscribe 和Unsubscribe 向Mqtt Broker发送消息的方法,以及On*** 负责接收来自Mqtt Broker消息的回调方法。MqttHandler作为管道里的最后一个Handler,负责接收来自Mqtt Broker的消息,转发给MqttClient。

    在MqttClient基础上,可以方便的进行扩展,例如HeartbeatMqttClient就是在管道中加入了Idle和Ping两个Handler,实现定时发送PING包完成心跳功能。    

测试一:订阅/发布相同主题

    在云端服务器上运行mosquitto Mqtt Broker。通过如下代码,向服务器订阅test/1主题,然后再向test/1主题每秒发送 0-7,收到0-7,验证了Connect, Disconnect, Publish,Subscribe。

            Mqtt.Client.MqttClient mqttClient = new Mqtt.Client.MqttClient();
            var result = await mqttClient.ConnectAsync("127.0.0.1", 1883);
            Console.WriteLine($"connect {result.Success}");
            if (result.Success)
            {
                await mqttClient.SubscribeAsync("test/1", DotNetty.Codecs.Mqtt.Packets.QualityOfService.AtLeastOnce, (packet) =>
                {
                    var pubpacket = (DotNetty.Codecs.Mqtt.Packets.PublishPacket)packet;
                    Console.WriteLine(pubpacket.Payload.GetString(0, pubpacket.Payload.WriterIndex, UTF8Encoding.UTF8));
                });
                await Task.Delay(1000);
                for(int i = 0; i < 8; i++)
                {
                    await mqttClient.PublishAsync("test/1", UTF8Encoding.UTF8.GetBytes(i.ToString()));
                    await Task.Delay(1000);
                }
                await Task.Delay(1000);
                await mqttClient.DisconnectAsync();
            }

 

测试二:心跳

            Mqtt.Client.HeartbeatMqttClient mqttClient = new Mqtt.Client.HeartbeatMqttClient();
            var result = await mqttClient.ConnectAsync("127.0.0.1", 1883);
            Console.WriteLine($"connect {result.Success}");
            if (result.Success)
            {
                await Task.Delay(100000);
                await mqttClient.DisconnectAsync();
            }

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值