13

作为连接到 mosquitto 的 mqtt 客户端,是否可以检索也连接到代理的客户端 ID 列表?

4

6 回答 6

10

实现这一点的一种方法是让客户端在每次连接代理时发布主题为“status/client-id”和有效负载“1”的消息,并在断开连接时发布有效负载“0”的消息。

然后在服务器(代理)端,设置另一个客户端订阅主题“状态/#”,当它收到任何这样的消息时,将客户端 ID 和有效负载(连接或未连接)存储到数据库中。

然后您可以读取数据库以准确了解哪个客户端在线或离线。

于 2013-03-12T05:53:15.437 回答
5

方法一:在客户端逻辑中处理

正如@user1048839 所说,使用客户端LWT和在线发布消息,维护自定义主题的客户端状态。下标此主题并自行维护客户列表。

如果 pub retainmsg,一旦 sub 将获取客户端列表。

方法二:修改mosquitto代理代码

官方代码不支持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.线上/线下活动

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 retainmsg, sub this topic 可以获得所有客户端的在线状态(在有效负载中)。

在github上测试源代码:

4-在线列表

5-在线活动

于 2018-12-19T23:41:57.523 回答
4

您大概可以通过 BASH 命令 netstat、grep 以及必要时的 awk 获取此信息。如果 Mosquitto 正在使用端口 1883,那么以下内容将告诉您我相信您想要什么:

须藤网络统计 | grep:1883

于 2016-09-22T04:55:50.857 回答
2

不。

最好在 mosquitto 邮件列表中讨论这个问题:https ://launchpad.net/~mqtt-users

于 2012-03-19T19:31:06.313 回答
2

一个很好的解决方法是让客户(如果可能)定义最后的遗嘱和遗嘱(LWT)。您的服务器将订阅 LWT 将发布到的特殊主题,并假定所有客户端都在线,除非它们发布到该主题。

MQTT 最后遗嘱的目的或用途是什么?

于 2014-09-06T10:31:51.877 回答
1

好吧,我现在使用 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);
?>
于 2012-03-20T13:53:40.623 回答