mqtt 协议之 PINGREQ, PINGRESP
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 < )
throw new Exception("The supplied header is invalid. Header must be at least 2 bytes long."); var byte1 = stream.ReadByte();
MessageType = (MessageType)((byte1 & 0xf0) >> );
Dup = ((byte1 & 0x08) >> ) > ;
Qos = (Qos)((byte1 & 0x06) >> );
Retain = (byte1 & 0x01) > ; //Remaining Length
//var byte2 = stream.ReadByte();
var lengthBytes = ReadLengthBytes(stream);
RemaingLength = CalculateLength(lengthBytes);
} public void WriteTo(Stream stream)
{
var flags = (byte)MessageType << ;
flags |= (Dup ? : ) << ;
flags |= (byte)Qos << ;
flags |= Retain ? : ; stream.WriteByte((byte)flags); //byte 1
if (RemaingLength == ) //byte 2
stream.WriteByte();
else
{
do
{
int digit = RemaingLength & 0x7f;
RemaingLength = RemaingLength >> ;
if (RemaingLength > )
digit = digit | 0x80;
stream.WriteByte((byte)digit);
} while (RemaingLength > );
}
} 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 reached
byte sizeByte;
int byteCount = ;
do
{
sizeByte = (byte)stream.ReadByte();
lengthBytes.Add(sizeByte);
} while (++byteCount <= && (sizeByte & 0x80) == 0x80); return lengthBytes.ToArray();
} internal static int CalculateLength(byte[] lengthBytes)
{
var remainingLength = ;
var multiplier = ; 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 = ,
CONNACK = ,
PUBLISH = ,
PUBACK = ,
PUBREC = ,
PUBREL = ,
PUBCOMP = ,
SUBSCRIBE = ,
SUBACK = ,
UNSUBSCRIBE = ,
UNSUBACK = ,
PINGREQ = ,
PINGRESP = ,
DISCONNECT =
} /// <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 = , /// <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 = , /// <summary>
/// QOS Level 2 - Message will be delivered once, and only once. Message will be retried until
/// it is successfully sent..
/// </summary>
ExactlyOnce = ,
}
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 协议之 PINGREQ, PINGRESP的更多相关文章
- MQTT 协议学习:007-Keep Alive 连接保活 与 对应报文(PINGREQ、PINGRESP)
背景 keep alive 是 CONNECT 报文中可变头的一部分. 我们提到过 Broker 需要知道 Client 是否非正常地断开了和它的连接,以发送遗愿消息.实际上 Client 也需要能够 ...
- MQTT协议(一)
MQTT(Message Queue Telemetry Transport),遥测传输协议,提供订阅/发布模式,更为简约.轻量,易于使用,针对受限环境(带宽低.网络延迟高.网络通信不稳定),可以简单 ...
- MQTT协议学习笔记
1.前沿 万物联网的时代即将到来,物联网也由当初的概念开始进一步落实.随着无线网络技术飞速发展,各种设备都可以连接网络,实现远程控制.例如智能家居最近非常火爆,智能插座.智能LED灯.智能摄像头等.在 ...
- 物联网MQTT协议分析和开源Mosquitto部署验证
在<物联网核心协议—消息推送技术演进>一文中已向读者介绍了多种消息推送技术的情况,包括HTTP单向通信.Ajax轮询.Websocket.MQTT.CoAP等,其中MQTT协议为IBM制定 ...
- Netty实现高性能IOT服务器(Groza)之手撕MQTT协议篇上
前言 诞生及优势 MQTT由Andy Stanford-Clark(IBM)和Arlen Nipper(Eurotech,现为Cirrus Link)于1999年开发,用于监测穿越沙漠的石油管道.目标 ...
- MQTT协议-MQTT协议解析(MQTT数据包结构)
协议就是通信双方的一个约定,即,表示第1位传输的什么.第2位传输的什么…….在MQTT协议中,一个MQTT数据包由:固定头(Fixed header). 可变头(Variable header). 消 ...
- MQTT协议笔记之连接和心跳
前言 本篇会把连接(CONNECT).心跳(PINGREQ/PINGRESP).确认(CONNACK).断开连接(DISCONNECT)和在一起. CONNECT 像前面所说,MQTT有关字符串部分采 ...
- MQTT协议实现Eclipse Paho学习总结
MQTT协议实现Eclipse Paho学习总结 摘自:https://www.cnblogs.com/yfliufei/p/4383852.html 2015-04-01 14:57 by 辣椒酱, ...
- 采用MQTT协议实现android消息推送(1)MQTT 协议简介
1.资料 mqtt官网 http://mqtt.org/ 服务端程序列表 https://github.com/mqtt/mqtt.github.io/wiki/servers 客户端库列表 http ...
随机推荐
- 【swupdate文档 二】许可证
许可证 SWUpdate是免费软件.它的版权属于Stefano Babic和其他许多贡献代码的人(详情请参阅实际源代码和git提交信息). 您可以根据自由软件基金会发布的GNU通用公共许可证第2版的条 ...
- 【openjudge】C15C Rabbit's Festival CDQ分治+并查集
题目链接:http://poj.openjudge.cn/practice/C15C/ 题意:n 点 m 边 k 天.每条边在某一天会消失(仅仅那一天消失).问每一天有多少对点可以相互到达. 解法:开 ...
- 《Java编程思想》阅读笔记一
Java编程思想 这是一个通过对<Java编程思想>(Think in java)第四版进行阅读同时对java内容查漏补缺的系列.一些基础的知识不会被罗列出来,这里只会列出一些程序员经常会 ...
- leetcode 之Candy(12)
这题的思路很巧妙,分两遍扫描,将元素分别和左右元素相比较. int candy(vector<int> &rattings) { int n = rattings.size(); ...
- 20:django中的安全问题
本节主要是讲解django中的安全特性,讲述django是如何应对网站一般面临的安全性问题 跨站点脚本(XXS)攻击 跨站点脚本攻击是指一个用户把客户端脚本注入到其他用户的浏览器中.通常是通过在数据库 ...
- Codeforces 707C Pythagorean Triples(构造三条边都为整数的直角三角形)
题目链接:http://codeforces.com/contest/707/problem/C 题目大意:给你一条边,问你能否构造一个包含这条边的直角三角形且该直角三角形三条边都为整数,能则输出另外 ...
- 简述MapReduce计算框架原理
1. MapReduce基本编程模型和框架 1.1 MapReduce抽象模型 大数据计算的核心思想是:分而治之.如下图所示.把大量的数据划分开来,分配给各个子任务来完成.再将结果合并到一起输出.注: ...
- 三:Storm设计一个Topology用来统计单词的TopN的实例
Storm的单词统计设计 一:Storm的wordCount和Hadoop的wordCount实例对比
- 熟悉并了解uml的使用(一)
本资料对UML各种模型图的构成和功能进行说明,通过本资料的学习达到可以读懂UML模型图的目的.本资料不涉及模型图作成的要点等相关知识. UML简介 UML (Unified Modeling Lang ...
- es6中对象的一些操坐
变量的赋值 key值得构建 对象的严格检测 对象的合并 1.变量的赋值: let name='宋宇',age='17岁': let obj={name,age} //快速的将变量引入到对象中去. 2. ...