Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get a list of connected client IDs from MQTT client

Tags:

client

mqtt

As a mqtt client connected to mosquitto is it possible to retrieve a list of client IDs who are also connected to the broker?

like image 932
Andreas Linden Avatar asked Mar 19 '12 08:03

Andreas Linden


People also ask

How many clients can be connected to an MQTT 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.

What is my MQTT client ID?

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.

How many devices can be connected to MQTT?

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.

How do I check my Mosquitto connection?

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.


6 Answers

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.

like image 143
horacex Avatar answered Oct 07 '22 15:10

horacex


method I: handle in client logic

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.

method II: change mosquitto broker code

official code not support online_list,
so I patched mosquitto 1.5.4, add 2 custom sys topic:

1. online list

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

2. online/offline event

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

like image 31
yurenchen Avatar answered Oct 07 '22 15:10

yurenchen


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

like image 36
CMP Avatar answered Oct 07 '22 15:10

CMP


No.

It might be better discussing this on the mosquitto mailing list: https://launchpad.net/~mqtt-users

like image 37
ralight Avatar answered Oct 07 '22 14:10

ralight


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?

like image 24
user1048839 Avatar answered Oct 07 '22 16:10

user1048839


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);
?>
like image 28
Andreas Linden Avatar answered Oct 07 '22 16:10

Andreas Linden