php-mqtt/client

read empty from socket in php7.4 throw error

wuxian12 opened this issue · 6 comments

Hello,
while read empty data from socket, in PHP 7.2 if ($receivedData === false) is false but in PHP 7.4 it is true:

[ERROR] Reading data from the socket from an MQTT broker failed.
[ERROR] While connecting to the MQTT broker at [192.168.0.51:8883], a transfer error occurred.
PHP Fatal error: Uncaught PhpMqtt\Client\Exceptions\ConnectingToBrokerFailedException: [1] Establishing a connection to the MQTT broker failed: A connection could not be established due to data transfer issues. in /opt/www/vendor/php-mqtt/client/src/MQTTClient.php:465
Stack trace:
#0 /opt/www/vendor/php-mqtt/client/src/MQTTClient.php(147): PhpMqtt\Client\MQTTClient->performConnectionHandshake()
#1 /opt/www/app/MQTT/Publish/MQTTAbstractPublish.php(88): PhpMqtt\Client\MQTTClient->connect()
#2 /opt/www/app/Listener/MainWorkerStartListener.php(32): App\MQTT\Publish\MQTTAbstractPublish->reconnect()
#3 /opt/www/vendor/hyperf/event/src/EventDispatcher.php(48): App\Listener\MainWorkerStartListener->process()
#4 /opt/www/vendor/hyperf/framework/src/Bootstrap/WorkerStartCallback.php(50): Hyperf\Event\EventDispatcher->dispatch()
#5 {main} thrown in /opt/www/vendor/php-mqtt/client/src/MQTTClient.php on line 465

The following is my code to debug the situation:

var_dump('read data............'.$receivedData, $receivedData === false);

if ($receivedData === false) {
    $this->logger->error('Reading data from the socket from an MQTT broker failed.', [
        'broker' => sprintf('%s:%s', $this->host, $this->port),
    ]);

    throw new DataTransferException(self::EXCEPTION_RX_DATA, 'Reading data from the socket failed. Has it been closed?');
}

return $receivedData;

Am I right that you are using the latest version (v0.3.0) of the package? And what type of broker are you using (Mosquitto, HiveMQ, ...)?

My testing has been done on PHP 7.4 and the automated tests on GitHub are also testing PHP 7.4 (besides PHP 7.2 and 7.3). So maybe you also leave some additional information about your setup (operating system, environment, etc.).

The version is up to date, Broker is EMQx, and the PHP version is built by Docker,docker is base on alpine

Which options are you using to connect to the broker (TLS, username/password, clean session flag, etc.)? From the port I can only infer you are using TLS.

this is my options , $setting = new ConnectionSettings( MQTTClient::QOS_EXACTLY_ONCE, false, false, 10, 0, 10, null, null, false, true, true);

Sounds alright and works fine for me, to be honest. Since I do not have a valid SSL certificate for testing, I swapped the TLS settings (useTls: true, tlsVerifyPeer: false, tlsVerifyName: false instead of useTls: false, tlsVerifyPeer: true, tlsVerifyName: true). I ran it locally and in a docker container (docker run --rm -v $PWD:/work -w /work namoshek/php-mssql:7.4-cli php /work/subscribe.php) against an EMQx broker (docker run --rm -it -p 18083:18083 -p 1883:1883 -p 8883:8883 emqx/emqx:latest). I used one of my pre-built PHP images since I know that ext-pcntl is installed there. If alpine makes a difference, then I'm not sure I can help. But maybe you can try to find out if that's the case anyway.

Two things I noticed about your configuration though:

  • A keep alive interval of 0 makes no sense - you don't want to ping your server that often. The default (10) is a reasonable value, and even 1 would be fine. But 0 means send a ping during each loop iteration. That's overkill.
  • Your TLS settings (useTls: false, tlsVerifyPeer: true, tlsVerifyName: true) don't make much sense to me. Unless you are using a CA file, you are not actually using TLS. For testing purposes with a self-signed certificate, useTls: true, tlsVerifyPeer: false, tlsVerifyName: false makes more sense. For a production environment, you should set all three to true.

thank you,Let me see if there is a broker problem