Get a list of connected client IDs from MQTT clien

2020-02-25 23:42发布

问题:

As a mqtt client connected to mosquitto is it possible to retrieve a list of client IDs who are also connected to the broker?

回答1:

method I: handle in client logic

as @user1048839 says, use client's LWT & online publish msg, maintain client status on a custom topic. subscript this topic & maintain client list self.

if pub retain msg, once sub will get the client list.

method II: change mosquitto broker code

official code not support online_list,
so I patched mosquitto 1.5.4, add 2 custom sys topic:

1. online list

mosquitto_sub -i DDD -v -t '$SYS/broker/chen_list'
$SYS/broker/chen_list
0 - CLOUD0_19108
1 - EEE
2 - DDD

2. online/offline event

mosquitto_sub -i DDD -v -t '$SYS/broker/chen_state/#'
$SYS/broker/chen_state/DDD 1
$SYS/broker/chen_state/EEE 1
$SYS/broker/chen_state/CLOUD0_19108 1
$SYS/broker/chen_state/EEE 0
$SYS/broker/chen_state/EEE 1

// if pub retain msg, sub this topic can get all clients online state (in payload).

source on github:

4-online-list

5-online-event



回答2:

one way to implement this is let the client publish a message with topic "status/client-id" and payload "1" every time when it connects the broker, and with payload "0" when it disconnects.

Then on the server(broker) side, setup another client subscribe to the topic "status/#", when it gets any message like this, store the client-id and payload(connected or not) into database.

then you can read the database to know exactly which client is online or offline.



回答3:

No.

It might be better discussing this on the mosquitto mailing list: https://launchpad.net/~mqtt-users



回答4:

A good work-around for this is to have the clients(if possible) define a Last will and testament(LWT). Your server will subscribe to a special topic where the LWT will be published to and assume all clients as online unless they publish to that topic.

MQTT what is the purpose or usage of Last Will Testament?



回答5:

You could presumably get this information via the BASH commands netstat, grep and if necessary awk. If Mosquitto is using port 1883 then the following will tell you what you want I believe:

sudo netstat | grep :1883



回答6:

well i now created a workaround using a PHP script: it starts the mosquitto broker, reads the output and if someone connects or disconnects it sends an xml string with the connected clients to the broker. (the posted code is a bit simplified as I adiddionally query a database for more information about the user)

<?php
require('SAM/php_sam.php');

if (!$handle = popen('mosquitto 2>&1', 'r')) {

    die('could not start mosquitto');
}

function usersToXML($users) {

    $xml = '<?xml version="1.0"?><userlist>';
    foreach($users as $user) {

        $xml .= '<user>' .
            '<id><![CDATA['. $user->id .']]></id>' .
            '</user>';
    }

    $xml .= '</userlist>';
    return $xml;
}

function updateBroadcast($users) {

    sleep(1);
    ob_start();
    $conn = new SAMConnection();
    $conn->Connect(SAM_MQTT, array(
        SAM_HOST => '127.0.0.1',
        SAM_PORT => 1883
    ));

     $conn->Send('topic://broadcast', (object)array('body' => usersToXML($users)));
     $conn->Disconnect();
     ob_end_clean();
}

while($line = fread($handle, 2096)) {

    echo $line;
    if (preg_match('/New client connected from .+ as user_(\d+)./', $line, $regs)) {

        $user = (object)array('id' => $regs[1]);
        $connectedUsers[$user->id] = $user;
        updateBroadcast($connectedUsers);

    } else if (preg_match('/Received DISCONNECT from user_(\d+)/', $line, $regs) ||
        preg_match('/Client user_(\d+) has exceeded timeout, disconnecting./', $line, $regs) ||
        preg_match('/Socket read error on client user_(\d+), disconnecting./', $line, $regs)) {

        if (isset($connectedUsers[$regs[1]])) {

            unset($connectedUsers[$regs[1]]);
            updateBroadcast($connectedUsers);
        }
    }
}

pclose($handle);
?>


标签: client mqtt