Mqtt ----心跳机制

心跳机制

  Keep Alive指定连接最大空闲时间T,当客户端检测到连接空闲时间超过T时,必须向Broker发送心跳报文PINGREQ,Broker收到心跳请求后返回心跳响应PINGRESP。若Broker超过1.5T时间没收到心跳请求则断开连接,并且投递遗嘱消息到订阅方;同样,若客户端超过一定时间仍没收到心跳响应PINGRESP则断开连接。 
  连接空闲时发送心跳报文可以降低网络请求,弱化对带宽的依赖。

Keep Alive设定时机

  创建连接时,在CONNECT报文中指定,单位s。

Client Take-Over

场景:客户端与Broker连接正常,然后客户端快速重启(小于1.5T),再重新连接Broker,在未达到1.5T这段时间内,客户端与Broker存在两条连接。 
处理措施: 先断开之前的连接再建立新的连接。

 mqtt 协议里最简单的是 ping 协议吧 (心跳包), ping 协议是已连接的客户端发往服务端, 告诉服务端,我还"活着"

PINGREQ - PING request

fixed header format.

bit 7 6 5 4 3 2 1 0
byte 1 Message Type (12) DUP flag QoS level RETAIN
  1 1 0 0 x x x x
byte 2 Remaining Length (0)
  0 0 0 0 0 0 0 0

no variable header

no payload

response:   The response to a PINGREQ message is a PINGRESP message.

PINGRESP - PING response

fixed header

bit 7 6 5 4 3 2 1 0
byte 1 Message Type (13) DUP flag QoS level RETAIN
  1 1 0 1 x x x x
byte 2 Remaining Length (0)
  0 0 0 0 0 0 0 0

no variable header

no payload

------------------------------------------------------------------------ 华丽的分界线 ---------------------------------------

客户端会在一个心跳周期内发送一条PINGREQ消息到服务器端。两个字节,固定值。

服务器收到PINGREQ请求之后,会立即响应一个两个字节固定格式的PINGRESP消息。

周期定义在 心跳频率在CONNECT(连接包)可变头部“Keep Alive timer”中定义时间,单位为秒,无符号16位short表示。

ok ,上代码 :

固定头部 FinedHeader

    /// <summary>/// Fixed header/// </summary>internal class FixedHeader{/// <summary>/// Message type/// </summary>public MessageType MessageType { get; set; }/// <summary>/// DUP flag/// </summary>public bool Dup { get; set; }/// <summary>/// QoS flags/// </summary>public Qos Qos { get; set; }/// <summary>/// RETAIN 保持/// </summary>public bool Retain { get; set; }/// <summary>/// Remaining Length 剩余长度/// 单个字节最大值:01111111,16进制:0x7F,10进制为127。/// MQTT协议规定,第八位(最高位)若为1,则表示还有后续字节存在。/// MQTT协议最多允许4个字节表示剩余长度。/// 最大长度为:0xFF,0xFF,0xFF,0x7F,/// 二进制表示为:11111111,11111111,11111111,01111111,十进制:268435455/// </summary>public int RemaingLength { get; set; }public FixedHeader() { }public FixedHeader(Stream stream){if (stream.Length < 2)throw new Exception("The supplied header is invalid. Header must be at least 2 bytes long.");var byte1 = stream.ReadByte();MessageType = (MessageType)((byte1 & 0xf0) >> 4);Dup = ((byte1 & 0x08) >> 3) > 0;Qos = (Qos)((byte1 & 0x06) >> 1);Retain = (byte1 & 0x01) > 0;//Remaining Length//var byte2 = stream.ReadByte();var lengthBytes = ReadLengthBytes(stream);RemaingLength = CalculateLength(lengthBytes);}public void WriteTo(Stream stream){var flags = (byte)MessageType << 4;flags |= (Dup ? 1 : 0) << 3;flags |= (byte)Qos << 1;flags |= Retain ? 1 : 0;stream.WriteByte((byte)flags);     //byte 1if (RemaingLength == 0)         //byte 2stream.WriteByte(0);else{do{int digit = RemaingLength & 0x7f;RemaingLength = RemaingLength >> 7;if (RemaingLength > 0)digit = digit | 0x80;stream.WriteByte((byte)digit);} while (RemaingLength > 0);}}internal static byte[] ReadLengthBytes(Stream stream){var lengthBytes = new List<byte>();// read until we've got the entire size, or the 4 byte limit is reachedbyte sizeByte;int byteCount = 0;do{sizeByte = (byte)stream.ReadByte();lengthBytes.Add(sizeByte);} while (++byteCount <= 4 && (sizeByte & 0x80) == 0x80);return lengthBytes.ToArray();}internal static int CalculateLength(byte[] lengthBytes){var remainingLength = 0;var multiplier = 1;foreach (var currentByte in lengthBytes){remainingLength += (currentByte & 0x7f) * multiplier;multiplier *= 0x80;}return remainingLength;}}

消息父类: Message

    internal class Message{public FixedHeader FixedHeader { get; protected set; }public Message(){}public Message(MessageType messageType){FixedHeader = new FixedHeader{MessageType = messageType};}public virtual void WriteTo(Stream stream){}public static Message CreateFrom(byte[] buffer){using (var stream = new MemoryStream(buffer)){return CreateFrom(stream);}}public static Message CreateFrom(Stream stream){var header = new FixedHeader(stream);return CreateMessage(header, stream);}public static Message CreateMessage(FixedHeader header, Stream stream){switch (header.MessageType){case MessageType.CONNACK:return new ConnAckMessage(header, stream);case MessageType.DISCONNECT:return null;case MessageType.PINGREQ:return new PingReqMessage();case MessageType.PUBACK:return new PublishAckMessage(header, stream);case MessageType.PUBCOMP://return new MqttPubcompMessage(str, header);case MessageType.PUBLISH://return new MqttPublishMessage(str, header);case MessageType.PUBREC://return new MqttPubrecMessage(str, header);case MessageType.PUBREL://return new MqttPubrelMessage(str, header);case MessageType.SUBACK://return new MqttSubackMessage(str, header);case MessageType.UNSUBACK://return new MqttUnsubackMessage(str, header);case MessageType.PINGRESP:return new PingRespMessage(header, stream);case MessageType.UNSUBSCRIBE:case MessageType.CONNECT:case MessageType.SUBSCRIBE:default:throw new Exception("Unsupported Message Type");}}}

两个枚举:

MessageType  (消息类型)

Qos (服务质量等级)

    [Flags]public enum MessageType : byte{CONNECT     = 1,CONNACK     = 2,PUBLISH     = 3,PUBACK      = 4,PUBREC      = 5,PUBREL      = 6,PUBCOMP     = 7,SUBSCRIBE   = 8,SUBACK      = 9,UNSUBSCRIBE = 10,UNSUBACK    = 11,PINGREQ     = 12,PINGRESP    = 13,DISCONNECT  = 14}/// <summary>/// 服务质量等级/// </summary>[Flags]public enum Qos : byte{/// <summary>///     QOS Level 0 - Message is not guaranteed delivery. No retries are made to ensure delivery is successful./// </summary>AtMostOnce = 0,/// <summary>///     QOS Level 1 - Message is guaranteed delivery. It will be delivered at least one time, but may be delivered///     more than once if network errors occur./// </summary>AtLeastOnce = 1,/// <summary>///     QOS Level 2 - Message will be delivered once, and only once. Message will be retried until///     it is successfully sent../// </summary>ExactlyOnce = 2,}

ping 请求包:  PingReqMessage

响应包:         PingRespMessage

    internal sealed class PingReqMessage : Message{public PingReqMessage(): base(MessageType.PINGREQ){}public override void WriteTo(Stream stream){FixedHeader.WriteTo(stream);}}internal class PingRespMessage : Message{public PingRespMessage(): base(MessageType.PINGRESP){}public PingRespMessage(FixedHeader header, Stream stream){FixedHeader = header;}}

OK.

Mqtt ----心跳机制 长链接 ping相关推荐

  1. 【MQTT基础篇(十四)】MQTT心跳机制

    文章目录 MQTT心跳机制 MQTT心跳机制 在医院里,医生利用心跳来判断患者是否还有生命体征.对于MQTT服务器来说,它要判断一台MQTT客户端是否依然保持连接可以检查这台客户端是不是经常发送消息给 ...

  2. Netty心跳机制-长连接

    前文需求回顾 完成对红酒窖的室内温度采集及监控功能.由本地应用程序+温度传感器定时采集室内温度上报至服务器,如果温度 >20 °C 则由服务器下发重启空调指令,如果本地应用长时间不上传温度给服务 ...

  3. MQTT心跳机制介绍

    在医院里,医生利用心跳来判断患者是否还有生命体征.对于MQTT服务器来说,它要判断一台MQTT客户端是否依然保持连接可以检查这台客户端是不是经常发送消息给服务端.如果经常收到客户端的消息,那么没问题, ...

  4. Mqtt ----心跳机制

    心跳机制 Keep Alive指定连接最大空闲时间T,当客户端检测到连接空闲时间超过T时,必须向Broker发送心跳报文PINGREQ,Broker收到心跳请求后返回心跳响应PINGRESP.若Bro ...

  5. 移动端IM实践:实现Android版微信的智能心跳机制

    本文由微信开发团队人员编写,转自 WeMobileDev,感谢. 一 引言 在2013年11月中旬时,因为基础组件组人手紧张,Leo安排我和春哥去广州轮岗支援. 刚到广州的时候,Ray让我和春哥对Li ...

  6. 转 互联网推送服务原理:长连接+心跳机制(MQTT协议)

    http://blog.csdn.net/zhangzeyuaaa/article/details/39028369 目录(?)[-] 无线移动网络的特点 android系统的推送和IOS的推送有什么 ...

  7. mqtt如何发送心跳 安卓_互联网推送服务原理:长连接+心跳机制(MQTT协议)

    互联网推送消息的方式很常见,特别是移动互联网上,手机每天都能收到好多推送消息,经过研究发现,这些推送服务的原理都是维护一个长连接(要不不可能达到实时效果),但普通的socket连接对服务器的消耗太大了 ...

  8. 互联网推送服务原理:长连接+心跳机制(MQTT协议)

    互联网推送消息的方式很常见,特别是移动互联网上,手机每天都能收到好多推送消息,经过研究发现,这些推送服务的原理都是维护一个长连接(要不不可能达到实时效果),但普通的socket连接对服务器的消耗太大了 ...

  9. 移动互联网消息推送原理:长连接+心跳机制(MQTT协议)

    互联网推送消息的方式很常见,特别是移动互联网上,手机每天都能收到好多推送消息,经过研究发现,这些推送服务的原理都是维护一个长连接(要不不可能达到实时效果),但普通的socket连接对服务器的消耗太大了 ...

最新文章

  1. Highcharts+Spring饼图使用实例
  2. 妈妈花3万给9岁儿子报编程课 网友:全是忽悠!
  3. 360浏览器保存密码设置_电脑小技巧查看浏览器保存的系统账号密码
  4. 什么是validationQuery
  5. 区块链现状:最初的炒作消退,将迎来大量新应用(第一部分)
  6. [开源]在iOS上实现Android风格的控件Toast
  7. 雅虎14条性能优化原则
  8. mysql延迟写入概念_三分钟了解MySQL的简单概念
  9. 100个Python实战项目(十一)如何使用 Python 获取电话号码信息?
  10. qq空间把android改成iphone,qq空间改iPhone6 Plus方法 qq空间改手机型号教程
  11. uml通信图画法_UML各种图画法总结
  12. Unity学习笔记------用Unity2D制作打地鼠游戏
  13. 极米H5多少流明?采用新亮度标准的极米H5怎么样?性价比高吗?
  14. 浙大何越扬计算机系2 2,浙江大学第十一届大学生数学建模竞赛获奖名单.doc
  15. 易经六十四卦详解白话文解释——易经64卦全解(上)
  16. 机械设备租赁平台如何快速进行商户号分账?
  17. 椭圆型变分问题理论及数值方法
  18. List的removeAll方法异常
  19. Python 把csv文件转换为excel文件
  20. 腾讯云阿里云配置 mysql开放3306端口

热门文章

  1. php gps 车辆定位,员工GPS解决方案
  2. 摩托罗拉刷机维修服务器,摩托罗拉手机通用刷机教程
  3. JasperReport| TTF和TTC字体介绍
  4. 电大网考计算机基础知识,2017年电大计算机网考试题及答案
  5. 路由器为何会有特殊的默认路由(静态路由的一种特殊形式------默认路由)
  6. pytorch中的BatchNorm和LayerNorm
  7. 网页占满整个屏幕_CSS网页背景图片等比例占满整个页面的解决方案
  8. 浏览器下载文件不全解决方法
  9. Unity之2D摄像机跟随
  10. Jenkins+Docker+Spring+Java项目持续集成(单机版)