美文网首页
php mtt扩展踩坑总结

php mtt扩展踩坑总结

作者: 魂狩 | 来源:发表于2019-06-27 19:38 被阅读0次

mqtt协议是时下比较好用的发布/订阅模式协议。但是在具体使用的过程中,使用PHP的mqtt扩展会遇到一些奇葩问题,这里是踩坑之后的总结。这里假设读者初步了解mqtt协议。

问题

  1. 使用基础用法,连接之后直接发布,有可能会出现消息没有发出去的情况。
    经过抓包之后发现,发送失败是因为php扩展在发送connect请求后,没有等待回应,直接发送publish请求然后断开连接。mqtt服务端发送connect ack包后没有收到tcp的ack包,当作连接失败,publish请求被抛弃。本地环境网络环境好,所以mqtt服务端可以收到connect ack包,发送成功;但是互联网环境就会有比较大的概率发送失败了。
    解决方法为在确认收到connect ack包后再断开连接:
<?php
$client = new Mosquitto\Client();
$client->isok=false;
$client->onConnect(function() use ($client) {
    $client->isok=true;
});
$client->connect("127.0.0.1", 1883, 5);
$client->publish('/hello', "Hello from PHP at " . date('Y-m-d H:i:s'));
$client->publish('/hello', "Hello from PHP at " . date('Y-m-d H:i:s'));
while (!$client->isok) {
    $client->loop();
}
$client->disconnect();

绝大多数情况下这样写就可以了,但是极端情况下还是可能会发送失败。如果要求一定发送成功,需要修改qos为1或者2。

  1. 使用以上方法,发送qos>0的消息会失败。
    原因是qos>0的消息要求服务器回复publish ack包,而上述方法在确认连接之后就断开连接了,publish ack包没有确认收到,服务端就将此消息抛弃了。解决方案是累加消息次数,收到ack包后将累加器减1,累加器到0了才断开连接:
<?php
$client = new Mosquitto\Client();
$client->num=0;
$client->connect("127.0.0.1", 1883, 5);
$client->onPublish(function() use ($client) {
    $client->num--;
});
$client->publish('/hello', "Hello from PHP1 at " . date('Y-m-d H:i:s'));
$client->publish('/hello', "Hello from PHP2 at " . date('Y-m-d H:i:s'),1);
$client->publish('/hello', "Hello from PHP3 at " . date('Y-m-d H:i:s'),2);
$client->num+=3;
while ($client->num>0) {
    $client->loop();
}
$client->disconnect();

这种方法对qos=0的消息无效,qos=0时没有ack包,onPublish函数会马上执行,可能连接还没有建立就断开了,出现问题1。

总结

大多数情况下,使用qos=0,使用相对简单的写法就可以了。一般mqtt服务端和php服务器都在一个内网中,异常情况基本可以忽略。
如果想写个更可靠的或者说更好的程序,那么最好的解决方案是:连接后进行阻塞,发一个消息后累加器+1,回调中-1,处理函数末尾阻塞确认消息都发完了才结束。完整代码如下:

<?php
$client = new Mosquitto\Client();
$client->num=0;
$client->isok=false;
$client->onConnect(function() use ($client) {
    $client->isok=true;
});
$client->onPublish(function() use ($client) {
    $client->num--;
});
while ($client->num>0) {
    $client->loop();
}
$client->connect("127.0.0.1", 1883, 5);
$client->publish('/hello', "Hello from PHP1 at " . date('Y-m-d H:i:s'));
$client->publish('/hello', "Hello from PHP2 at " . date('Y-m-d H:i:s'),1);
$client->publish('/hello', "Hello from PHP3 at " . date('Y-m-d H:i:s'),2);
$client->num+=3;
while ($client->num>0) {
    $client->loop();
}
$client->disconnect();

相关文章

  • php mtt扩展踩坑总结

    mqtt协议是时下比较好用的发布/订阅模式协议。但是在具体使用的过程中,使用PHP的mqtt扩展会遇到一些奇葩问题...

  • PHP7升级总结

    /* 记录两个在php7升级过程中踩的坑。*/ 一、扩展的不兼容 问题现象: 1、升级完php7的机器中,有几台从...

  • 总结 Linux 下安装 PHP 扩展步骤

    总结一下 Linux 下安装 PHP 扩展步骤,这里以安装 PHP 的 redis 扩展为例。 一、拿到扩展包下载...

  • PHP踩坑

    修改php.ini不生效 通过phpinfo()查看发现修改的位置也是正确的 ,但是重启Apache后依然无法生效...

  • PHP安装imagick扩展踩过的坑

    环境背景:WAMP(PHP7.1.9 + Apache2.4.27) 最近需要使用到图形添加水印等操作,于是找到了...

  • Flutter 开发记录

    Flutter 开发踩坑记录(干货总结)

  • windows redis安装与PHP扩展安装

    坑1:需要使用有php扩展支持的redis版本 首先看下PHP的redis扩展支持哪些redis版本(最新版本的r...

  • 个人博客标签分类

    【小结】零碎的小结 【踩坑记录】报错等记录,防止再度踩坑 【总结】比较完整的总结 【想法】自己的一些想法和推论 【...

  • 仿阿里系优酷网-企业级Go改造PHP项目踩坑避坑指北 无密

    仿阿里系优酷网-企业级Go改造PHP项目踩坑避坑指北 无密 【点击下载】 互联网早期为快速上线,不少网站基于PHP...

  • [php]踩坑实录

    1、strpos()函数的返回值false与0问题 strpos函数定义:int strpos ( string ...

网友评论

      本文标题:php mtt扩展踩坑总结

      本文链接:https://www.haomeiwen.com/subject/lsrdcctx.html