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

问题描述:

由于连接到mosquitto的mqtt客户端可以检索也连接到代理的客户端ID列表吗?从MQTT客户端获取已连接客户端ID的列表

以及我现在创建使用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); 
?> 
+1

与我的非常相似。我用另一个客户端来管理“status/client-id”主题。 – horacex 2013-03-12 13:01:55

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

一个方法是让客户端发布消息,主题为“状态/客户端ID”和每次连接代理时有效载荷“1”,断开连接时有效载荷“0”。

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

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

+0

如果你会读,你会知道我只是在我自己一年之前就明白了这一点;) – 2013-03-12 10:35:44

+0

有用的知识。你找到一个更好/更有效的方法来做到这一点? :)只是想更好地学习 – horacex 2013-03-12 13:00:21

+1

只使用LWT而不是期望客户端在断开连接时发布消息。 – 2015-10-19 20:38:02

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

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

通过BASH命令netstat的,grep和必要时的awk你大概可以得到这个信息。如果Mosquitto使用的是1883端口,那么以下将告诉你我想要的东西:

sudo netstat | grep:1883