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 ...
随机推荐
- [c++,bson] linux 使用 BSON 编程[www]
[c++,bson] linux 使用 BSON 编程 http://blog.chinaunix.net/uid-28595538-id-4987410.html 1.js db=db.getSib ...
- 安装icephp 记
下面开始安装: 一:yum 安装 首先需要添加一个yum源. # vi /etc/yum.repos.d/zeroc-ice-amzn.repo写入: [zeroc-ice]name=Ice 5 fo ...
- 1006. Team Rankings
Description It's preseason and the local newspaper wants to publish a preseason ranking of the teams ...
- 【2017 Multi-University Training Contest - Team 1】小结
啊人生第一次打多校被虐 紧随yql的脚步做题. 1001: 可以发现我们平时表示的数都是$x*log_{10}{10}$,所以类似于做一个换底公式就可以了. -1是一个烟雾弹,因为小学生都知道2^n不 ...
- windows访问linux共享文件夹
1.windows的网上邻居,是通过smb协议来共享信息的,如果需要给访问linux上的共享目录被windows访问到,需要linux有smb协议 sudo apt-get install samba ...
- shell中引号的作用(转)
引号的作用 1 双引号(“”) 1)使用””可引用除字符$(美元符号).`(反引号).\(反斜线)外的任意字符或字符串.双引号不会阻止shell对这三个字符做特殊处理(标示变量名.命令替换.反斜线转义 ...
- java中的逻辑运算符,以及&与&&的区别,|与||的区别
原创,转载请留言联系 逻辑运算符: & 与 false&true=false:true&true=true:false&false=false 必须两个都是true才返 ...
- AC日记——[SCOI2009]游戏 bzoj 1025
[SCOI2009]游戏 思路: 和为n的几个数最小公倍数有多少种. dp即可: 代码: #include <bits/stdc++.h> using namespace std; #de ...
- ffmpeg测试程序
ffmpeg在编译安装后在源码目录运行make fate可以编译并运行测试程序.如果提示找不到ffmpeg的库用LD_LIBRARY_PATH指定一下库安装的目录.
- 图片上传功能(EasyUI前台框架+SSM框架)
文件上传步骤: * 1.采用文件正确的接收方式(修改3处配置文件/接口类型等) * 2.判断是否为一个图片,0表示无异常,1代表异常(jpg|gif|png) * 3.判断是不是一个“正经”的图片,判 ...