控制报文结构 MQTT 控制报文由三部分组成,按照 下图描述的顺序: 固定报头 每个 MQTT 控制报文都包含一个固定报头。下图描述了固定报头的格式,固定报头的第一字节是固定的,用于表示控制报文类型和标志位,不再赘述请参考 MQTT协议规范 紧接的是剩余长度这里重点记录一下剩余长度的含义以及计算方式。 剩余长度 **剩余长度(Remaining Length)**表示当前报文剩余部分的字节数,包括可变报头(Variable header)和负载(Payload)的数据 剩余长度字段使用一个变长度编码方案,从byte2开始,最多可达4个字节,也就是说可能用byte2~byte5来编码表示剩余长度 对于小于128的值使用单字节编码,大 …
阅读更多一些容易搞混的概念: QoS是发送者和接受者之间的协议,而不是Publisher和Subscriber之间的协定,Subscriber订阅到的消息的QoS和Publisher没有直接关系 Subscriber订阅到的消息的QoS:Publisher发布消息到Broker的QoS为QoSA,Subscriber从Broker订阅消息的QoS为QoSB,取QoSA和QoSB这二者的最小值 QoS 0:最多分发一次 消息的分发依赖于底层网络的能力。接收者不会发送响应,发送者也不会重试。消息可能送达一次也可能根本没送达。 QoS1:至少分发一次 服务质量确保消息至少送达一次。QoS 1 的 PUBLISH 报文的可变报头中包含一个报文标识 …
阅读更多保留消息(Retained) 保留消息是指在 PUBLISH 数据包中 Retain 标识设为 1 的消息,Broker 收到这样的 PUBLISH 包以后,将保存这个消息以及它的QoS,当有一个新的订阅者订阅相应主题的时候,Broker 会马上将这个消息发送给订阅者。 保留消息具有以下特点: 一个 Topic 只能有 1 条保留消息,发布新的保留消息将覆盖老的保留消息 如果订阅者使用通配符订阅主题,它会收到所有匹配的主题上的保留消息,如下所示 保留消息发送到订阅者时,消息的 Retain 标识仍然是 1,订阅者可以判断这个消息是否是保留消息,以做相应的处理。同时,订阅者收到的消息的QoS与保留消息一致 只有新的订阅者才会收到保留消 …
阅读更多本文记录一些学些MQTT的过程中的重点和难点,学习材料包括: MQTT协议规范 MQTT 协议学习: 总结 与 各种定义的速查表 - schips - 博客园 (cnblogs.com) 角色 MQTT Broker - 消息代理服务器 MQTT Client - 消息发布者,通过QoS和Topic发布和订阅消息。MQTT Client可以同时是Publisher和Subscriber 订阅 包含一个主题和QoS 订阅与单个会话关联,一个会话可以包含一个或者多个订阅 主题名和主题过滤器 以下内容多来自MQTT3.1.1规范 MQTT Client通过主题发布和订阅消息。主题名可以有不同层级,通过/划分。主题可能是管理员在服务端预先定 …
阅读更多参考资料: 字符编码笔记:ASCII,Unicode 和 UTF-8 - 阮一峰的网络日志 (ruanyifeng.com) List of Unicode characters - Wikipedia 相关概念 字符:是对文字和符号的总称,例如汉字、拉丁字母、emoji 都是字符 Unicode码点(Code Point):在Unicode字符集中,每个字符都对应一个唯一数,这个唯一数就是Unicode码点。码点范围:U+0000 - U+10FFFF(十六进制)。这个范围可以容纳超过100万个字符 字符平面(Plane):将字符进行分组,每组容纳65536(2^16)个字符,每一组称为一个平面,一共划分了17 …
阅读更多安装 Mac下通过brew安装Mosquitto只需要一条简单的命令:brew install mosquitto 1mosquitto has been installed with a default configuration file. 2You can make changes to the configuration by editing: 3 /usr/local/etc/mosquitto/mosquitto.conf 4 5To restart mosquitto after an upgrade: 6 brew services restart mosquitto 7Or, if you don't …
阅读更多本文是《C Primer Plus》第六章至第八章读书笔记,持续更新中。 ch06. C控制语句:循环 C语言支持哪些循环控制关键字 循环体中(里)变量的作用域 可以通过scanf函数控制循环 - 如果输入数据无法转换成指定类型的时候,scanf函数返回0 while循环部分要点:只有测试条件之后的单独语句(简单或者符合语句)才是循环部分 (一般编程习惯好的都不会出现这种情况,但是也得了解如果出现这种情况到底是因为什么。现代高级的IDE都会有相应的提醒) 1int n = 0; 2while (n < 3) 3 printf("n is %d\n", n); 4 n++; // 这里的n++已经不是循环体的一部 …
阅读更多本文是《C Primer Plus》第九章至第十一章读书笔记,持续更新中。 ch09. 函数 函数原型、函数定义和函数调用 函数的参数列表和返回值 形参和实参 函数类型 函数原型:任何程序在使用函数之前都要声明改函数的类型。在函数调用前需要声明函数原型。函数原型是告诉编译器函数的类型。对于较小的函数,也可以把函数定义放在主调函数之前,这时候的函数定义也就是函数声明 函数定义:提供函数的实际代码 声明带有参数的函数时,可以只给定参数的类型而不需要提供参数的名字,比如:void show_n_char(char, int); 函数参数 - 主调函数通过参数将值传递给被调函数 形式参数(formal argument) - 函数定义和声明 …
阅读更多本文是《C Primer Plus》第三章至第五章读书笔记。 ch03. 数据和C 思考问题: 各种类型的数据占用多少空间 各种类型的数据是如何格式化输出的 一般而言,存储int需要占用一个机器字长 C语言中的byte不是8个bit,而是和一个char占用的位长一样 char根据编译器不同,可能被处理成有符号也可能被处理成无符号。具体可以查看头文件limits.h 整数类型一般都被存储为int类型,当超过int最大范围,编译器会自动将其视为高一个等级的类型,直到越界 2^16 = 65536 / 2^8 = 256 浮点数的存储:有效数和指数部分(包括符号),3.16e^7,有效数部分就是3.16 float至少能表示6位有效数 …
阅读更多本文是《C Primer Plus》第十二章至第十四章读书笔记,持续更新中。 ch12. 存储类别、链接和内存管理 不同关键字修饰是否对应不同的存储类别 怎么管理内存,是否有对应的函数 标识符 - 一个名称(变量),用于指向内存中的特定对象。通过作用域和链接来描述标识符的可见性。 左值 - 指定内存对象的标识符或者表达式 可修改的左值 - 可以使用左值改变对象中的值 const char* pc = "Behold a string literral!" pc - 可以修改的左值,即pc可以指向别的地址 *pc - 不可修改的左值,*pc指向'B',不可修改 作用域 块作用域 - 花括号括起来的代码区域。以前块作 …
阅读更多