从MQTT客户端获取已连接客户端ID的列表

时间:2012-03-19 08:34:25

标签: client mqtt

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

6 个答案:

答案 0 :(得分:8)

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

然后在服务器(代理)端,设置另一个客户端订阅主题“status /#”,当它收到这样的消息时,将client-id和payload(已连接或未连接)存储到数据库中。

然后您可以读取数据库以确切知道哪个客户端在线或离线。

答案 1 :(得分:3)

没有

在mosquitto邮件列表上讨论这个问题可能会更好:https://launchpad.net/~mqtt-users

答案 2 :(得分:2)

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

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

答案 3 :(得分:1)

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

sudo netstat | grep:1883

答案 4 :(得分:1)

方法I:处理客户端逻辑

正如@ user1048839所说,使用客户端的LWT并在线发布消息, 在自定义主题上维护客户状态。 为该主题添加下标并维护客户列表自身。

如果pub retain消息,则sub将获得客户端列表。

方法二:更改蚊帐经纪人代码

官方代码不支持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

//如果发布retain消息,则本主题下的子主题可以使所有客户端处于联机状态(在有效负载中)。

github上的源代码:

4-online-list

5-online-event

答案 5 :(得分:0)

我现在使用PHP脚本创建了一个解决方法:它启动mosquitto代理,读取输出,如果有人连接或断开连接,它会将连接的客户端的xml字符串发送给代理。 (发布的代码有点简化,因为我在adiddionally查询数据库以获取有关用户的更多信息)

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