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的更多相关文章

  1. MQTT 协议学习:007-Keep Alive 连接保活 与 对应报文(PINGREQ、PINGRESP)

    背景 keep alive 是 CONNECT 报文中可变头的一部分. 我们提到过 Broker 需要知道 Client 是否非正常地断开了和它的连接,以发送遗愿消息.实际上 Client 也需要能够 ...

  2. MQTT协议(一)

    MQTT(Message Queue Telemetry Transport),遥测传输协议,提供订阅/发布模式,更为简约.轻量,易于使用,针对受限环境(带宽低.网络延迟高.网络通信不稳定),可以简单 ...

  3. MQTT协议学习笔记

    1.前沿 万物联网的时代即将到来,物联网也由当初的概念开始进一步落实.随着无线网络技术飞速发展,各种设备都可以连接网络,实现远程控制.例如智能家居最近非常火爆,智能插座.智能LED灯.智能摄像头等.在 ...

  4. 物联网MQTT协议分析和开源Mosquitto部署验证

    在<物联网核心协议—消息推送技术演进>一文中已向读者介绍了多种消息推送技术的情况,包括HTTP单向通信.Ajax轮询.Websocket.MQTT.CoAP等,其中MQTT协议为IBM制定 ...

  5. Netty实现高性能IOT服务器(Groza)之手撕MQTT协议篇上

    前言 诞生及优势 MQTT由Andy Stanford-Clark(IBM)和Arlen Nipper(Eurotech,现为Cirrus Link)于1999年开发,用于监测穿越沙漠的石油管道.目标 ...

  6. MQTT协议-MQTT协议解析(MQTT数据包结构)

    协议就是通信双方的一个约定,即,表示第1位传输的什么.第2位传输的什么…….在MQTT协议中,一个MQTT数据包由:固定头(Fixed header). 可变头(Variable header). 消 ...

  7. MQTT协议笔记之连接和心跳

    前言 本篇会把连接(CONNECT).心跳(PINGREQ/PINGRESP).确认(CONNACK).断开连接(DISCONNECT)和在一起. CONNECT 像前面所说,MQTT有关字符串部分采 ...

  8. MQTT协议实现Eclipse Paho学习总结

    MQTT协议实现Eclipse Paho学习总结 摘自:https://www.cnblogs.com/yfliufei/p/4383852.html 2015-04-01 14:57 by 辣椒酱, ...

  9. 采用MQTT协议实现android消息推送(1)MQTT 协议简介

    1.资料 mqtt官网 http://mqtt.org/ 服务端程序列表 https://github.com/mqtt/mqtt.github.io/wiki/servers 客户端库列表 http ...

随机推荐

  1. linux pthread【转】

    转自:http://www.cnblogs.com/alanhu/articles/4748943.html Posix线程编程指南(1) 内容:  一. 线程创建  二.线程取消 关于作者  线程创 ...

  2. mount/umount命令【转】

    转自:http://www.cnblogs.com/qq78292959/archive/2012/03/06/2382334.html 如果想在运行的Linux下访问其它文件系统中的资源的话,就要用 ...

  3. C高级 框架开发中红黑树结构

    引言  -- 红黑树历史 红黑树是数据结构学习中一道卡. 底层库容器中必不可少的算法. 历经各种实战运用,性能有保障. 同样红黑树不好理解, 就算理解了, 代码也不好写. 就算写了, 工程库也难构建. ...

  4. [linux]通过ssh远程设定各服务器时间,从而实现集群时间同步

    #!/usr/bin/env bash #all hosts should to sync time, all hosts should no password login echo other sy ...

  5. 查看linux 下进程运行时间(转)

    原文地址:http://blog.csdn.net/tspangle/article/details/11731317 可通过ps 来查看,通过参数 -o 来查看 如: ps -eo pid,tty, ...

  6. JS页面之间传值

    父页面与子页面之间有多种传值的方式: 第一种,通过window.open的方法打开一个新的页面,在新的页面里面通过window.opener来获取对象,以下为实例 父页面: function open ...

  7. 写微信API所遇到的问题

    1.接口还没出来之前. 根据微信网页版的页面,自己做了页面,分成了两个页面,一个是登录之后的,一个是登录之前的.后来接口出来之后我师兄说要做成只有一个页面时,我就有点吓到了,想想都觉得难,后来用了JQ ...

  8. 【转载】viewLoad、viewDidLoad的一些事

    viewLoad和viewDidLoad都可以用来在视图载入的时候,初始化一些内容 viewDidLoad此方法只有当view从nib文件初始化的时候才被调用.viewDidLoad用于初始化,加载时 ...

  9. Django如何使文件在django自动执行

    1. Django admin源码中 admin.py from django.contrib import admin # Register your models here. 在admin源码中 ...

  10. 微信小程序实战篇-图片的预览、二维码的识别

    开篇 今天,做的小程序项目要求,个人中心的客服图片在用户长按时可以识别其二维码,各种翻阅查找,采坑很多,浪费了很多时间,在这里记录下需要注意的点,以及对小程序官方提供的API做一个正确和清晰的认知,希 ...