Получить список идентификаторов подключенных клиентов от клиента MQTT - PullRequest
9 голосов
/ 19 марта 2012

Как клиент mqtt, подключенный к mosquitto, можно ли получить список идентификаторов клиентов, которые также подключены к брокеру?

Ответы [ 6 ]

9 голосов
/ 12 марта 2013

Один из способов реализовать это - позволить клиенту публиковать сообщение с темой «status / client-id» и полезной нагрузкой «1» каждый раз, когда он подключается к брокеру, и с полезной нагрузкой «0», когда он отключается.

Затем на стороне сервера (брокера) настройте другого клиента, подписавшегося на тему «status / #», когда он получит любое подобное сообщение, сохраните идентификатор клиента и полезные данные (подключенные или нет) в базе данных.

тогда вы можете прочитать базу данных, чтобы точно знать, какой клиент онлайн или оффлайн.

3 голосов
/ 19 марта 2012

Нет.

Возможно, лучше обсудить это в списке рассылки mosquitto: https://launchpad.net/~mqtt-users

2 голосов
/ 06 сентября 2014

Хороший обходной путь для этого состоит в том, чтобы клиенты (если это возможно) определяли Последнее завещание (LWT).Ваш сервер подпишется на специальную тему, в которой LWT будет публиковаться, и будет предполагать, что все клиенты находятся в сети, если только они не публикуют эту тему.1004 *

1 голос
/ 20 декабря 2018

метод I: обрабатывать в логике клиента

, как говорит @ user1048839, использовать LWT клиента и онлайн публиковать сообщения, поддерживать статус клиента в пользовательской теме.подпишите эту тему и сохраните список клиентов самостоятельно.

если pub retain msg, как только sub получит список клиентов.

метод II: изменить код брокера комаров

officialкод не поддерживается online_list ,
, поэтому я пропатчил mosquitto 1.5.4, добавив 2 пользовательских раздела sys:

1.онлайн список

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

2.событие online / offline

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

// если pub retain msg, в этом разделе можно получить состояние всех клиентов в сети (в полезной нагрузке).

источник на github:

4-online-list

5-online-event

1 голос
/ 22 сентября 2016

Предположительно, вы можете получить эту информацию с помощью команд BASH netstat, grep и, при необходимости, awk. Если Mosquitto использует порт 1883, тогда я скажу вам, что вы хотите:

sudo netstat | grep: 1883

0 голосов
/ 20 марта 2012

Хорошо, теперь я создал обходной путь, используя скрипт PHP: он запускает посредник mosquitto, читает выходные данные и, если кто-то подключается или отключается, отправляет посреднику строку xml с подключенными клиентами.(опубликованный код немного упрощен, поскольку я дополнительно запрашиваю базу данных для получения дополнительной информации о пользователе)

<?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);
?>
...