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 ...
随机推荐
- Laravel 5.2 一、安装与目录结构
一.Laravel 安装 这里选择通过 Composer 的 create-project 命令来安装 Laravel 应用. composer create-project laravel/lara ...
- VPS性能测试方法小结(8)
1.为了能够得到更为准确和详细的有关VPS主机性能测试数据,我们应该多角度.全方位地运行多种VPS性能测试工具来进行检测,同时也要记得排除因本地网络环境而造成的数据结果的错误. 2.VPS主机性能跑分 ...
- Spring,tk-mapper源码阅读
Mybatis的源码学习(一): 前言: 结合spring本次学习会先从spring-mybatis开始分析 在学习mybatis之前,应该要对spring的bean有所了解,本文略过 先贴一下myb ...
- ajax之深入解析(2)
我们前面实现了用原生的JavaScript代码实现ajax的异步数据传输.接下来,我们再使用一个流行的js框架jQuery来实现ajax. 通过 jQuery AJAX 方法,我们能够使用 HTTP ...
- 前趋图和PV操作
- 8:django sessions(会话)
django会话 django提供对匿名会话全方位的支持,会话框架可以存储和检索每个站点访问者的任意数据.会话数据是存储在服务器端的,并且简要了发送和接受cookie的过程,cookies只包含一个s ...
- ZOJ-3319
Islands Time Limit: 1 Second Memory Limit: 32768 KB There are N islands and some directed paths ...
- php文件上传需要的配置
服务端配置(php.ini) 1.file_uploads=On //支持HTTP上传 2.upload_tmp_dir =”” //临时文件保存的目录 3.upload_max_filesize ...
- APP线上问题收集信息整理
常话说“软件是不能保证百分百没有bug的”,因此当我们的APP上线之后,市场的使用人员会反馈一些我们测试人员可能在测试时遗漏的问题,包括也不防会有一些需求的反馈,这些问题均由售后人员反馈整理,以一种方 ...
- 如何配置Java环境,包括JDK,Maven等
下载JDK并安装 搜索JDK,官网立马就出来了,下载之后个人觉得毕竟开发,毕竟这东西不大,C盘稳一点,安装在C盘可以的 配置 右键打开计算机->属性->高级系统设置->高级-> ...