I have setup a node js server with Mosca running on it. Clients are able to connect to the Mosca server and publish a message. I need to the send an acknowledgment in the form of a message(subscribed to some topic) back to the client.
The below code sends multiple messages continuously once the message is published by the client. Am I missing anything?
var settings = {
port: 1882,
backend: ascoltatore
};
var message = {
topic: 'crofters',
payload: 'OK', // or a Buffer
qos: 2
};
var server = new mosca.Server(settings);
server.on('clientConnected', function(client) {
console.log('client connected', client.id);
});
// fired when a message is received
server.on('published', function(packet, client ) {
var packet_payload = packet.payload;
packet_payload = packet_payload.toString();
console.log('Published', packet_payload);
server.publish(message, function() {
console.log('done!');
});
});
server.on('ready', setup);
function setup() {
console.log('Mosca server is up and running');
}
The event listener server.on('published', function(packet, client){...} listens to every publishing events, including the server's.
What is happening is that when you use server.publish(message, function(){...}) inside that listener it triggers another published event, which is immediately caught by the listener.
It never stops publishing because it never stops catching its own events.
I have been facing similar issues. If you notice, Mosca has only QoS 0 and Qos 1
So I suppose the broker tries to send the same message more than once "at least once" until it receives some acknowledgement from a client. Check this document out
Related
I'm trying to learn SocketIo in NodeJS. I'm using .on and .emit functions with same event name but server dont see incoming event emitted by client but client recive some strange numbers as data to event.
I was trying to change .on to .addListener but this is still not working.
Server:
const io = require('socket.io');
const server = io.listen(8089);
server.on('connect', socket => {
console.log('New connection!') // this line is working fine!
socket.on('ping', incomingMessage => {
console.log('Incoming message!');
socket.emit('pong', incomingMessage);
});
});
Client code:
Im using cdn from: https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js
const server = io('http://127.0.0.1:8089');
server.on('connect', () => {
server.on('pong', message => {
console.log('Incoming message! ', message);
});
server.emit('ping', 'test message');
})
But i dont see 'Incoming message' in server side terminal. Client sucessfully connected to server socket and after ~ 5 seconds i recive strange messages like:
- Incoming message! 1
- Incoming message! 3
- Incoming message! 4
in webbrowser console (using Opera)
Ok so i fixed this issue :v the problem was ping-pong event names that already was used by socket.io if i changed event names everything is working fine.
I tried client 1 and client 2 program I can able to easily communicate with them. I can easily send the messages and receive the messages with them, but I don't know if one client is disconnected, how can I send the disconnected message to subscribed clients.
client 1:
var mqtt=require("mqtt");
var express=require("express");
var app=express();
var options={
keepalive:100,
port: 1883,
clientId:'1',
clientSession:false,
host: "http://localhost:8000",
will:
{
topic:'willMag',
payload:"connection closed abnormallly r",
qos:1,
retain:true
}
};
var client=mqtt.connect("tcp://192.168.43.137:1883",options);
client.on("connect",function()
{
setInterval(function()
{
client.publish("ranjith/princy","hello love you princy",function()
{
console.log("message published in client1");
});
},2000);
client.subscribe("bv/nivi");
client.on("message",function(topic,message)
{
console.log("I recieved the topic:"+topic);
console.log("I recieved the message:"+message);
});
});
client.on("disconnect",function()
{
console.log("disconnected client1");
});
app.listen(8000,function()
{
console.log("server listen at port 8000");
});
client 2:
var mqtt=require("mqtt");
var express=require("express");
var app=express();
var options={
keepalive:100,
port: 1883,
clientId:'2',
clientSession:false,
host: "http://localhost:8086",
will:
{
topic:'willMag',
payload:"connection closed abnormallly b",
qos:1,
retain:true
}
};
var client=mqtt.connect("tcp://192.168.43.137:1883",options);
client.on("connect",function()
{
setInterval(function(){
client.publish("bv/nivi","hello love you nivi",function()
{
console.log("message published in client2");
});
},2000);
client.subscribe("ranjith/princy");
client.on("message",function(topic,message)
{
console.log("I recieved the topic:"+topic);
console.log("I recieved the message:"+message);
});
});
client.on("disconnect",function()
{
console.log("disconnected client2");
});
app.listen(8086,function()
{
console.log("server listen at port 8000");
});
It's not totally clear what you are asking here, but:
With MQTT you can not know what clients are subscribed to what topics
There is no way to know if a message has been delivered to a specific client
You can build a system to determine if a client is probably online. You need to make use of the Last Will and Testament (LWT) feature.
When your client connects it publishes a retained message to a given topic (e.g. client1/online payload: 1)
You set the LWT to publish payload 0 to the same topic if the client goes off line due to a crash/network failure
When you shut the client down cleanly you need to publish a 0 to the topic manually as the LWT will only fire if there is a failure.
Am learning MQTT and facing some issues understanding MQTT with RabbitMQ from http://blog.airasoul.io/the-internet-of-things-with-rabbitmq-node-js-mqtt-and-amqp/.
So, the issue here is when I run publisher code, a queue is added mqtt-subscription-test-qos1 but when I message doesn't get added in that queue. Although I've added binding of amq.topic to this queue with key-binding 'presence'.
This is my publisher code
var payload = {
message : 'Hello'
};
var client = mqtt.connect(url, { clientId: 'test-', clean:true});
client.on('connect', function () {
client.publish('presence', JSON.stringify(payload), { qos: 1 }, function() {
console.log("Sent");
client.end();
process.exit();
});
});
and below is my subscriber code.
var client = mqtt.connect(url, { clientId: 'test-', clean:true});
client.on('connect', function () {
client.subscribe('presence', { qos: 1 });
});
client.on('message', function (topic, message) {
console.log('received message ', message.toString());
});
This works, when I don't declare any options with connect function in publisher code. So what I don't get is, isn't publisher supposed to create a queue and then publish to topics?
What am I doing wrong?
You don't need to create a queue before publishing to the topic. When you publish first MQTT message, a queue gets created automatically with the default exchange name "amq.topic" and binding key same as your topic name.
I suspect your subscriber is not receiving the messages published since it starts and subscribes to the topic AFTER the publisher publishes the messages. Try by starting your subscriber first and then start your publisher.
I'm starting to work with Socket.io and my nodeJS API
I succeeded to get my user connected, and showed a message on my server.
But now, I'm trying to send data to my client -> then server -> then client again etc.
But when I use emit nothing appends... So this i my code :
SERVER SIDE
io.on('connection', function(socket){
console.log("user connected") // I see that
socket.emit('text', 'it works!'); //
socket.on('test1', function (data) {
console.log('received 1 : '); // Never showed
console.log(data); // Never showed
});
}
CLIENT SIDE
var socket = io.connect(myUrl); // good connection
socket.emit ('test1', {map: 4, coords: '0.0'}); // never showed on the server side
socket.on('text', function(text) {
alert(text); // never showed
socket.emit('test', { "test": "test2" });
});
Any ideas?
thanks !
Your Starter Code seems to be valid, you need to check two things :
if you successfully included the socket.min.js in the client side
if you re having any error printed in the console
On the client side, you have to wait until the connection succeeds before it is safe to send data to the server. Connecting to the server is not synchronous or instantaneous (thus it is not ready immediately). You are trying to send data before the connection is ready.
Put your first send of data inside a socket.on('connect', ...) handler.
var socket = io.connect(myUrl); // good connection
// send some data as soon as we are connected
socket.on('connect', function() {
socket.emit ('test1', {map: 4, coords: '0.0'});
});
socket.on('text', function(text) {
alert(text); // never showed
socket.emit('test', { "test": "test2" });
});
this worked for me
CLIENT SIDE
//sending custom data to server after successful connection
socket.on('connect', function(){
this.socket.emit('client-to-server', {map: 4, coords: '0.0'});
});
//listening the event fired by the socket server
socket.on('server-to-client', function(dataSendbyTheServer){
// do whatever you want
console.log(dataSendbyTheServer);
});
SERVER SIDE
io.on('connection', function(socket) {
// listening the event fired by the client
socket.on('client-to-server', function (data) {
console.log('received 1 : ');
// sending back to client
io.emit('server-to-client', data)
});
});
I am trying to implement a functionality wherein when a user is viewing a page, he should be automatically subscribed a Redis channel unique to that user. And all message published to that Redis channel should be received by the client side.
Below is by client side code,
var socket = io.connect('localhost:5000');
socket.on('connect', function(){
socket.emit("subscribe",$("#app_id").text());
});
socket.on('message', function(message) {
$("#lst").append("<li>" + message + "</li>")
});
And on the nodejs server, I have below code,
var client = redis.createClient();
io.sockets.on('connection', function (socket) {
socket.on("subscribe",function(channel){
client.subscribe(channel);
socket.join(channel);
});
client.on("message", function(channel, message){
socket.broadcast.to(channel).emit('message', message);
});
});
When I open the client page in two separate browsers, its subscribing to the two channels correctly and message published to those Redis channels are shown at client side. But if I refresh the page, the number of messages which I get is double and if I refresh again, it adds up. I guess the listeners getting added-up on each refresh.
I have coded the Redis listener inside the socket.io connection listener because I want to emit the message to the socket.This may be cause of the problem am facing. Dono how else to do it as I need socket instance to send message to client side. Please help on this.
as you already told: remove the listener on disconnect.
Have a look at how-to-remove-redis-on-message-listeners and socket-io-handling-disconnect-event for further reading.
untested sample
var client = redis.createClient();
io.sockets.on('connection', function (socket) {
var broadcast = function(channel, message){
socket.broadcast.to(channel).emit('message', message);
}
socket.on("subscribe",function(channel){
client.subscribe(channel);
socket.join(channel);
});
socket.on('disconnect', function() {
client.unsubscribe(channel);
client.removeListener(broadcast)
})
client.on("message", broadcast);
});