php-mqtt / client
一个用 PHP 编写和为 PHP 设计的 MQTT 客户端。
Requires
- php: ^8.0
- myclabs/php-enum: ^1.7
- psr/log: ^1.1|^2.0|^3.0
Requires (Dev)
- phpunit/php-invoker: ^3.0
- phpunit/phpunit: ^9.0
- squizlabs/php_codesniffer: ^3.5
Suggests
- ext-redis: Required for the RedisRepository
- dev-master
- v2.1.0
- v2.0.0
- v1.8.1
- v1.8.0
- v1.7.1
- v1.7.0
- v1.6.0
- v1.5.0
- v1.4.0
- v1.3.0
- v1.2.0
- v1.1.3
- v1.1.2
- v1.1.1
- v1.1.0
- v1.0.0
- v1.0.0-rc1
- 0.3.x-dev
- v0.3.0
- 0.2.x-dev
- v0.2.1
- v0.2.0
- 0.1.x-dev
- v0.1.5
- v0.1.4
- v0.1.3
- v0.1.2
- v0.1.1
- v0.1.0
- dev-dependabot/github_actions/sonarsource/sonarcloud-github-action-3.0.0
- dev-feature/require-php-8
- dev-feature-redis-repository-on-master
This package is auto-updated.
Last update: 2024-08-26 06:55:29 UTC
README
php-mqtt/client
由 Marvin Mall 创建并维护。它允许您连接到 MQTT 代理,在代理上发布消息并订阅主题。当前实现支持所有 QoS 级别(存在限制)。
安装
该包在 packagist.org 上可用,可以使用 composer
进行安装
composer require php-mqtt/client
该包需要 PHP 版本 8.0 或更高。
使用方法
以下仅提供了几个非常基本的示例。对于更详细的示例,请查看 php-mqtt/client-examples
仓库。
发布
使用 QoS 0 的非常基本的发布示例需要三个步骤:连接、发布和断开连接
$server = 'some-broker.example.com'; $port = 1883; $clientId = 'test-publisher'; $mqtt = new \PhpMqtt\Client\MqttClient($server, $port, $clientId); $mqtt->connect(); $mqtt->publish('php-mqtt/client/test', 'Hello World!', 0); $mqtt->disconnect();
如果您不想传递 $clientId
,则会为您生成一个随机客户端 ID。这基本上会隐式地强制一个干净会话。
请注意,大多数方法都可以抛出异常。上述示例没有添加任何异常处理,以保持简洁。
订阅
订阅比发布更复杂,因为它需要运行一个事件循环,该循环从代理读取、解析和处理消息
$server = 'some-broker.example.com'; $port = 1883; $clientId = 'test-subscriber'; $mqtt = new \PhpMqtt\Client\MqttClient($server, $port, $clientId); $mqtt->connect(); $mqtt->subscribe('php-mqtt/client/test', function ($topic, $message, $retained, $matchedWildcards) { echo sprintf("Received message on topic [%s]: %s\n", $topic, $message); }, 0); $mqtt->loop(true); $mqtt->disconnect();
当循环活动时,您可以使用 $mqtt->interrupt()
向循环发送中断信号。这将终止循环,在它开始下一次迭代之前。例如,您可以使用 pcntl_signal(SIGINT, $handler)
调用此方法
pcntl_async_signals(true); $clientId = 'test-subscriber'; $mqtt = new \PhpMqtt\Client\MqttClient($server, $port, $clientId); pcntl_signal(SIGINT, function (int $signal, $info) use ($mqtt) { $mqtt->interrupt(); }); $mqtt->connect(); $mqtt->subscribe('php-mqtt/client/test', function ($topic, $message, $retained, $matchedWildcards) { echo sprintf("Received message on topic [%s]: %s\n", $topic, $message); }, 0); $mqtt->loop(true); $mqtt->disconnect();
客户端设置
如上述示例所示,MqttClient
以服务器、端口和客户端 ID 作为前三个参数。第四个参数可以传递协议级别。目前支持 MQTT v3.1,作为常量 MqttClient::MQTT_3_1
提供。第五个参数允许传递存储库(默认情况下,只有 MemoryRepository
可用)。最后,第六个参数可以传递日志记录器。如果没有提供,则使用空日志记录器。
示例
$mqtt = new \PhpMqtt\Client\MqttClient( $server, $port, $clientId, \PhpMqtt\Client\MqttClient::MQTT_3_1, new \PhpMqtt\Client\Repositories\MemoryRepository(), new Logger() );
Logger
必须实现 Psr\Log\LoggerInterface
。
连接设置
MqttClient
的 connect()
方法接受两个可选参数
- 一个
ConnectionSettings
实例 - 一个布尔标志,指示是否请求一个干净会话(随机客户端 ID 会隐式地这样做)
示例
$mqtt = new \PhpMqtt\Client\MqttClient($server, $port, $clientId); $connectionSettings = (new \PhpMqtt\Client\ConnectionSettings) ->setConnectTimeout(3) ->setUseTls(true) ->setTlsSelfSignedAllowed(true); $mqtt->connect($connectionSettings, true);
ConnectionSettings
类通过流畅的接口提供了一些设置。本身是不可变的,并且将为每个添加的选项创建一个新的 ConnectionSettings
实例。这也防止了在建立连接之后更改连接设置。
以下是一个选项的完整列表及其相应的默认值
$connectionSettings = (new \PhpMqtt\Client\ConnectionSettings) // The username used for authentication when connecting to the broker. ->setUsername(null) // The password used for authentication when connecting to the broker. ->setPassword(null) // Whether to use a blocking socket when publishing messages or not. // Normally, this setting can be ignored. When publishing large messages with multiple kilobytes in size, // a blocking socket may be required if the receipt buffer of the broker is not large enough. // // Note: This setting has no effect on subscriptions, only on the publishing of messages. ->useBlockingSocket(false) // The connect timeout defines the maximum amount of seconds the client will try to establish // a socket connection with the broker. The value cannot be less than 1 second. ->setConnectTimeout(60) // The socket timeout is the maximum amount of idle time in seconds for the socket connection. // If no data is read or sent for the given amount of seconds, the socket will be closed. // The value cannot be less than 1 second. ->setSocketTimeout(5) // The resend timeout is the number of seconds the client will wait before sending a duplicate // of pending messages without acknowledgement. The value cannot be less than 1 second. ->setResendTimeout(10) // This flag determines whether the client will try to reconnect automatically // if it notices a disconnect while sending data. // The setting cannot be used together with the clean session flag. ->setReconnectAutomatically(false) // Defines the maximum number of reconnect attempts until the client gives up. // This setting is only relevant if setReconnectAutomatically() is set to true. ->setMaxReconnectAttempts(3) // Defines the delay between reconnect attempts in milliseconds. // This setting is only relevant if setReconnectAutomatically() is set to true. ->setDelayBetweenReconnectAttempts(0) // The keep alive interval is the number of seconds the client will wait without sending a message // until it sends a keep alive signal (ping) to the broker. The value cannot be less than 1 second // and may not be higher than 65535 seconds. A reasonable value is 10 seconds (the default). ->setKeepAliveInterval(10) // If the broker should publish a last will message in the name of the client when the client // disconnects abruptly, this setting defines the topic on which the message will be published. // // A last will message will only be published if both this setting as well as the last will // message are configured. ->setLastWillTopic(null) // If the broker should publish a last will message in the name of the client when the client // disconnects abruptly, this setting defines the message which will be published. // // A last will message will only be published if both this setting as well as the last will // topic are configured. ->setLastWillMessage(null) // The quality of service level the last will message of the client will be published with, // if it gets triggered. ->setLastWillQualityOfService(0) // This flag determines if the last will message of the client will be retained, if it gets // triggered. Using this setting can be handy to signal that a client is offline by publishing // a retained offline state in the last will and an online state as first message on connect. ->setRetainLastWill(false) // This flag determines if TLS should be used for the connection. The port which is used to // connect to the broker must support TLS connections. ->setUseTls(false) // This flag determines if the peer certificate is verified, if TLS is used. ->setTlsVerifyPeer(true) // This flag determines if the peer name is verified, if TLS is used. ->setTlsVerifyPeerName(true) // This flag determines if self signed certificates of the peer should be accepted. // Setting this to TRUE implies a security risk and should be avoided for production // scenarios and public services. ->setTlsSelfSignedAllowed(false) // The path to a Certificate Authority certificate which is used to verify the peer // certificate, if TLS is used. ->setTlsCertificateAuthorityFile(null) // The path to a directory containing Certificate Authority certificates which are // used to verify the peer certificate, if TLS is used. ->setTlsCertificateAuthorityPath(null) // The path to a client certificate file used for authentication, if TLS is used. // // The client certificate must be PEM encoded. It may optionally contain the // certificate chain of issuers. ->setTlsClientCertificateFile(null) // The path to a client certificate key file used for authentication, if TLS is used. // // This option requires ConnectionSettings::setTlsClientCertificateFile() to be used as well. ->setTlsClientCertificateKeyFile(null) // The passphrase used to decrypt the private key of the client certificate, // which in return is used for authentication, if TLS is used. // // This option requires ConnectionSettings::setTlsClientCertificateFile() and // ConnectionSettings::setTlsClientCertificateKeyFile() to be used as well. ->setTlsClientCertificateKeyPassphrase(null); // The TLS ALPN is used to establish a TLS encrypted mqtt connection on port 443, // which usually is reserved for TLS encrypted HTTP traffic. ->setTlsAlpn(null);
功能
- 支持的 MQTT 版本
- v3(只是不要使用 v3.1 特性,如用户名和密码)
- v3.1
- v3.1.1
- v5.0
- 传输
- TCP(未加密)
- TLS(加密,使用证书授权文件验证对等方)
- 连接
- 最后遗嘱
- 消息保留
- 身份验证(用户名 & 密码)
- TLS加密连接
- 干净会话(可以设置并发送,但客户端对QoS 2消息没有持久性)
- 发布
- QoS级别0
- QoS级别1(限制:会话之间没有持久状态)
- QoS级别2(限制:会话之间没有持久状态)
- 订阅
- QoS级别0
- QoS级别1
- QoS级别2(限制:会话之间没有持久状态)
- 支持的消息长度:无限大 (没有限制,尽管MQTT协议支持多达256MB,但实际上不应该使用,更不用说其他用途了)
- 日志记录可能(可以传递
Psr\Log\LoggerInterface
给客户端) - 持久性驱动程序
- 内存驱动程序
- Redis驱动程序
限制
- 消息流中QoS级别高于0的消息不会被持久化,因为默认实现使用内存存储库来存储数据。为了避免消息流中断的问题,请使用干净会话标志来表示您不关心旧数据。这不仅将指示代理将连接视为新的(没有以前的状态),而且还将重置已注册的存储库。
开发和测试
证书(TLS)
要运行测试(特别是TLS测试),您需要创建证书。已经为此提供了一个命令
sh create-certificates.sh
这将创建在.ci/tls/
目录下所需的所有证书。同样的脚本也用于持续集成。
测试用例的MQTT代理
运行测试预期MQTT代理正在运行。运行MQTT代理的最简单方法是使用Docker
docker run --rm -it \ -p 1883:1883 \ -p 1884:1884 \ -p 8883:8883 \ -p 8884:8884 \ -v $(pwd)/.ci/tls:/mosquitto-certs \ -v $(pwd)/.ci/mosquitto.conf:/mosquitto/config/mosquitto.conf \ -v $(pwd)/.ci/mosquitto.passwd:/mosquitto/config/mosquitto.passwd \ eclipse-mosquitto:1.6
当从项目目录运行时,这将启动一个Mosquitto MQTT代理,配置为使用生成的TLS证书和自定义配置。
如果您打算运行不同的代理或使用不同的方法,或者使用公共代理,您需要相应地调整在phpunit.xml
中定义的环境变量。
许可证
php-mqtt/client
是开源软件,根据MIT许可证授权。