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,000 clients can easily be handled by any decent MQTT broker; there's a benchmark from Scalagent which shows that a PC with: a 3 GHz Intel Core 2 Duo processor.
The client identifier (ClientId) identifies each MQTT client that connects to an MQTT broker. The broker uses the ClientId to identify the client and the current state of the client. Therefore, this Id should be unique per client and broker.
By increasing the range of ports to 1024 and 65535 so the available ports for any application would be (65535-1024 = 64511) We can get around 64k connections with different source port from a single source IP. This is the reason we are maintaining around 64k connections from load balancer to each message broker.
If you are using Windows, open up a command prompt and type 'netstat -an'. If your server is running, you should be able to see the port 1883. If you cannot go to Task Manager > Services and start/restart the Mosquitto server from there.
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.
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.
official code not support online_list,
so I patched mosquitto 1.5.4, add 2 custom sys topic:
mosquitto_sub -i DDD -v -t '$SYS/broker/chen_list'
$SYS/broker/chen_list
0 - CLOUD0_19108
1 - EEE
2 - DDD
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).
test source code on github:
4-online-list
5-online-event
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
No.
It might be better discussing this on the mosquitto mailing list: https://launchpad.net/~mqtt-users
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?
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 additionally 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);
?>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With