通过抓包的方式来介绍和学习 MQTT 协议,结合真实存在的网络字节,让 PHP 程序猿不存在学习压力,循序渐进的了解熟悉 MQTT 协议
在 5G 时代的背景下,我们也将迎来一个万物互联的时代,习惯了平常的 Web 应用开发,学习一下物联网相关技术也是对自己技术一大提升。
PHP 作为脚本语言,官方定位是一个适合 Web 开发的语言,那么如何使用 PHP 开发一个物联网应用?
首先我们需要知道物联网中常用的一些通讯协议,例如MQTT
、Modbus
、Coap
等等。
这里我就以 MQTT
协议为例,讲解 PHP 如何来开发一个物联网应用?
PHP(“PHP: Hypertext Preprocessor”,超文本预处理器的字母缩写)是一种被广泛应用的开放源代码的多用途脚本语言,它可嵌入到 HTML 中,尤其适合 web 开发。
这句话是来自 PHP 官网,可见 PHP 官方对自己的定位就是 web 开发,但是尽管 PHP 的开发是以服务端脚本为目的,但事实上其功能远不局限与此…
它不但可以作为服务端脚本,也可以作为命令行脚本,当你在使用php -v
查看 PHP 版本或者php -m
查看安装的扩展时,这时你就在操作命令行脚本了。
了解过 Swoole 的小伙伴应该都知道:Swoole 的大部分功能只适用于 CLI 模式,也就是命令行脚本,在使用时就需要通过在命令中执行php index.php
这种方式来运行。
而且 PHP 还能编写桌面应用程序,关于如何编写桌面应用程序这里就不过多说明,感兴趣的可以去 GitHub 或者谷歌了解一下。
那么现在都已经到了 2021 年,你还仅仅使用 PHP 来进行 CRUD 吗?没有其他什么能做了?答案当然是不!
在 Swoole 的加持之下,PHP 现在可以开发:即时通信(IM
)、实时视频语音(WebRTC
)、网络游戏(斗地主、五子棋、魔兽世界、传奇 2)以及物联网(MQTT
),这些项目都可以在 GitHub 上找到。
既然要开发一个物联网项目,那么说到底什么是物联网?
物联网其实是互联网的一个延伸,互联网的终端是计算机(PC、服务器),我们运行的所有程序,无非都是计算机和网络中的数据处理和数据传输,除了计算机外,没有涉及任何其他的终端(硬件)。
物联网的本质还是互联网,只不过终端不再是计算机(PC、服务器),而是嵌入式计算机系统及其配套的传感器。
这是计算机科技发展的必然结果,为人类服务的计算机呈现出各种形态,如穿戴设备、环境监控设备、虚拟现实设备等等。
只要有硬件或产品连上网,发生数据交互,就叫物联网,万物相连的互联网。
那么 PHP 应该如何去开发物联网应用程序?
最常规的,也是对 PHP 程序员来说最简单的,首先就是后台模块,开发物联网项目的管理系统
这里就用到了 PHP 的 CRUD,开发起来也是很快的,例如:数据管理、报表管理、开关控制、设备管理、充值缴费等等,这些应该对于 PHP 程序员来说应该已经是得心应手了。
都说到这里了,也应该说一下重点了,那就是 PHP 如何进行 MQTT 协议解析来进行设备通讯交互呢?什么是 MQTT 协议?
MQTT 是一种基于发布/订阅(publish/subscribe)模式的"轻量级"通讯协议。
MQTT 协议是轻量、简单、开放和易于实现的,由于物联网的环境是非常特别的,所以 MQTT 遵循以下设计原则:
- 发布/订阅(Pub/Sub)模式,方便消息在传感器之间传递;
- 允许用户动态创建主题,零运维成本;
- 把传输量降到最低以提高传输效率;
- 把低带宽、高延迟、不稳定的网络等因素考虑在内;
PHP 需要处理 MQTT 协议解析,这就要使用到 Swoole 扩展,它提供了一个选项:open_mqtt_protocol
,启用后会解析 MQTT 包头,Worker 进程的 onReceive 事件每次会返回一个完整的 MQTT 数据包。
也可以使用原生 PHP 来自己进行解析包头包体,这里我们就直接基于 Swoole 来使用演示。
同时还会用到 PHP 内置的一些函数,例如:pack/unpack
、ord/chr
以及位运算等
使用pack/unpack
来封包和解包,使用ord/chr
来转换Ascii
码
在开始分析之前,推荐安装两个应用来方便我们进行测试:
一个是 Wireshark,用来进行网络分析、抓包,这样我们就可以明显的看到 MQTT 客户端发来的数据包;
另外一个是 MQTT 客户端,用来模拟硬件发送数据。
MQTT v3 的协议一共有 14 种报文类型,v5 有 15 种类型,增加了 AUTH 类型。
通过 MQTT 的协议文档我们可以了解到每个数据包的第一个字节就是协议类型,而第二字节则为剩余长度,那么我们就可以通过位运算和 ord 来获取每个包的报文类型和剩余长度
如果剩余长度又是一个变长的编码,没有超过 128 的话,我们还可以这样获取,但是超过以后这样获取到是错误的数据
通过协议文档中的 C 示例代码,就可以转为使用 PHP 编写的代码:
这样我们就能正确获得到0
– 268435455
之间的剩余长度。
下面接着以第一个数据包类型 CONNECT 来作为说明,毕竟我们必须要先进行连接。
根据协议,在 CONNECT 包中,我们可以获取到以下数据:
- Protocol Name 协议名称
- Protocol Level 协议等级
- Connect Flags 连接标志
- Keep Alive 保持连接
- Client ID 客户端 ID
- Will Topic 遗嘱 topic
- Will Message 遗嘱消息
- User Name 用户名
- Password 密码
在 Connect Flags 包含了一些 Flag 位,用于表示是否设置了用户名密码、遗嘱消息、清除会话、QoS 等级等
我们来试着使用代码来获取一下这些信息,需要注意的是MQTT协议为大端序,即高位在前。
协议名称为4个字节,协议等级为1个字节
Connect Flags的数据包为1个字节,8个bit
CONNECT 数据包的有效载荷包含一个或多个带前缀的字段,这些字段的存在由变量头中的标志确定。
这些字段(如果存在)必须按客户端标识符,遗嘱主题,遗嘱消息,用户名,密码的顺序出现。
因为它们都是 utf-8 的字符串,所以我们可以封装一个方法来统一调用,减少了一部分重复代码。
这样我们就完成了一次 CONNECT 数据包的解析,在解析的时候会用到 unpack 和 ord,反之在封包的时候就会用到 pack 和 chr。
和对应的协议文档对应起来,似乎 MQTT 协议并没有那么困难,所以不要有压力,说自己搞不定…
当然你也可以直接使用我写的代码:simps/mqtt ,适用于 PHP 的 MQTT 协议解析和协程客户端,而且还是首个支持 MQTT v5.0 协议的 PHP 库。
支持 MQTT 协议 3.1、3.1.1 和 5.0 版本,支持QoS 0
、QoS 1
、QoS 2
。
以 CONNECT 数据包为例,证明 PHP 也可以使用 MQTT 协议来和设备通讯,当然不止这一个协议,Modbus
等也可以,并且也有 PHP 的实现库。
在这里也向大家介绍一个能让 PHP 支持嵌入式开发的工具:PHPoC
PHPoC (PHP on Chip):是一个编程语言和一个物联网硬件开发平台。
PHPoC 是基于泛用脚本语言 PHP 开发的可编程语言。
PHPoC 基本与 PHP 兼容,但为了嵌入式系统开发增加了 I/O
, UART
, I2C
, SPI
, ADC
, TIMER/COUNTER
, RTC
等支持硬件接口及硬件控制的新函数及功能。
这样我们就能基于它来编写嵌入式程序,这样就更加丰富了 PHP 的生态能力,感兴趣的可以了解一下。
本文正在参加腾讯云加社区技术创作 101 训练营,阅读 PDF 可以访问【技术创作 101 训练营】PHP 也能开发物联网应用程序
这个博客主题不错
一句话戳死你,windows不行~