Хорошо, теперь я создал обходной путь, используя скрипт 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);
?>