Connect to Socket.IO through socket.io-emitter - socket.io

I'm running two separate node.js processes. One runs Socket.IO and another Express.js. I'm trying to send an event from Express to the server running socket.io but by using socket.io-emitter a event only reaches sockets connected to the socket.io server. What I need is to be able to observe the same event that all other sockets are receing but on the socket.io server.

I used node_redis for interprocess communication. There's a Publish/Subscribe feature which is just what I wanted.
There's an example as below in https://github.com/NodeRedis/node_redis.
var redis = require("redis");
var sub = redis.createClient(), pub = redis.createClient();
var msg_count = 0;
sub.on("subscribe", function (channel, count) {
pub.publish("a nice channel", "I am sending a message.");
pub.publish("a nice channel", "I am sending a second message.");
pub.publish("a nice channel", "I am sending my last message.");
});
sub.on("message", function (channel, message) {
console.log("sub channel " + channel + ": " + message);
msg_count += 1;
if (msg_count === 3) {
sub.unsubscribe();
sub.quit();
pub.quit();
}
});
sub.subscribe("a nice channel");

Related

How to make websocket stream broadcast to many other pages?

I have a websocket stream being listened:
widget.channel.stream.listen((data) {
print("!!!!new msg: $data");
var dataJson = json.decode(data);
print(dataJson["content"]);
// do my job
setState(() {
_allAnimateMessages.insert(0, newMsg);
});
newMsg.animationController.forward();
});
But, when enter that page again, there was an error says:
Bad state: Stream has already been listened to.
How to make it as broadcast and other pages can receive that broadcast?
Solution for package web_socket_channel:
final channel = IOWebSocketChannel.connect(socketUrl);
final streamController = StreamController.broadcast();
streamController.addStream(channel.stream);
After that simply use streamController.stream to listen web socket events.
You can use broadcasts.
//Here is the solution
StreamController<String> streamController = new StreamController.broadcast(); //Add .broadcast here
//Now you can listen from various places
#override
void initState() {
super.initState();
print("Creating a StreamController...");
//First subscription
streamController.stream.listen((data) {
print("DataReceived1: " + data);
}, onDone: () {
print("Task Done1");
}, onError: (error) {
print("Some Error1");
});
//Second subscription
streamController.stream.listen((data) {
print("DataReceived2: " + data);
}, onDone: () {
print("Task Done2");
}, onError: (error) {
print("Some Error2");
});
streamController.add("This a test data");
print("code controller is here");
}
Font: https://medium.com/#ayushpguptaapg/using-streams-in-flutter-62fed41662e4
When using broadcasts you can have multiple listeners in the same stream.
If you simply use a stream without ".broadcast ()" you can only have one listener
As there are no useful answer, I update my answer here for other reference.
duplicate subscribe stream is a desired behaviour in flutter.
if you are just using a StreamBuilder, the stream can be listen only once. think about it, if your stream can be listen to many other pages or widgets, then data would be repeated.
But if you want using one single stream, and update all widgets
this is really can be occured when develop a complicated app, for example, you are building a chat app, new message comes, you should update many pages UI (your dialog chat ui, your session list ui....), then you should subscribe this streams in many pages, I still not found a proper way to do this, except make this stream to be broadcast, and do your work.

How to send and receive data from webstomp websocket provided by rabbitmq?

I am writing a chat application without explicit server side web socket.
I am using RabbitMQ webstomp as the web socket container and plain Javascript as the cleint to both send and receive data.
Below is the flow :
Browser -> native websocket/sockjs -> rabbitmq /sockjs websocket (ws://127.0.0.1:15674/ws or http://localhost:15674/stomp) -> put messages to queue.
However while testing the application, I am not able to send the data directly to ws://127.0.0.1:15674/ws. I am just able to connect to it.
I use the below template to send and receive data on client Javascript.
ws = new WebSocket('ws://127.0.0.1:15674/ws');
client = Stomp.over(ws);
client.connect('guest','guest',on_connection,on_connect_error,'/');
client.send(queue, {'reply-to':'/temp-queue/logs',priority: 9}, "msg" );
client.onreceive = func()
The problem,most likely,in your code is:
client.send(queue, {'reply-to':'/temp-queue/logs',priority: 9}, "msg" );
you have to send the message to a topic
I suggest to see the example here: https://github.com/rabbitmq/rabbitmq-web-stomp-examples
Here is a rapid example i made starting for the original example:
var client = Stomp.client('ws://localhost:15674/ws');
client.debug = pipe('#second');
var print_first = pipe('#first', function(data) {
client.send('/topic/test', {"content-type":"text/plain"}, data);
});
var on_connect = function(x) {
id = client.subscribe("/topic/test", function(d) {
print_first(d.body);
});
};
var on_error = function() {
console.log('error');
};
client.connect('guest', 'guest', on_connect, on_error, '/');

React Native Websocket Android not connecting to server

I'm trying to use React Native's built in Websocket support. I have this code:
var hostname = "192.168.X.XXX";
var port = "4567";
const webSocket = new WebSocket("ws://" + hostname + ":" + port + "/chat");
and I have this:
componentWillMount: function(){
console.log("MOUNTING CHAT COMPONENT");
webSocket.onopen = function(){
console.log("binding to chat room");
bindToChatRoom();
setTimeout(keepWebSocketOpen, 30000);
ws_connected = true;
};
webSocket.onmessage = function (msg) {
this.handleMsg(msg);
};
webSocket.onclose = function () {
console.log("WebSocket connection closed");
ws_connected = false;
};
webSocket.onerror = function (e){
//add some error handling -> DO THIS
console.log(e.message);
};
},
I'm running a local server using sparkjava, with this:
webSocket("/chat", ChatWebSocketHandler.class);
etc. I've tested the server, and I can connect to it (and send messages) both through both my web browser on my laptop AND on my phone with URL 192.168.x.xxx:4567/chat . However, when I run the react native app, I never see the console message "binding to chat room". Am I missing something? How come this websocket never opens?
Just want to note, I also tried connecting here:
ws://echo.websocket.org
which is described here:
http://www.websocket.org/echo.html
This is a known working websocket, so I know it's purely a react native issue...
Turns out that I had the line of code
const webSocket = new WebSocket("ws://echo.websocket.org");
in the wrong place. If you move it into componentWillMount, it works just fine.

Why websocket sendMessage is required

This is the code taken from the book "The Definitive Guide to HTML5 websocket"
div id="output"></div>
<script>
function setup() {
output = document.getElementById("output");
ws = new WebSocket("ws://localhost:7777");
ws.onopen = function(e) {
log("Connected");
sendMessage("Hello Websocket!");
}
ws.onclose = function(e){
log("Disconnected: " + e.reason);
}
ws.onerror = function(e){
log("Error ");
}
ws.onmessage = function(e) {
log("Message received: " + e.data);
ws.close();
}
}
function sendMessage(msg){
ws.send(msg);
log("Message Sent");
}
function log(s){
var p = document.createElement("p");
p.style.wordWrap = "break-word";
Could anybody please let me know for what reason this below event is required ??.
ws.send(msg);
I understand that the below will call the onMessage method on server side as shown below
public void onMessage(String data) {
}
But the actual purpose of onMessage on server side is to send data from backend to the javascript which will inturn call onmessage of client side javascript .
could anybody please help me understand this .
In the above code the ws.onopen, ws.onclose, ws.onmessage are all events associated with WebSocket object.
Whereas ws.send() is a method associated with WebSocket object. There is a huge difference between them.
The following event ensures that the Web Socket is connected to the server i.e you've opened your connection
ws.onopen = function(e) {
//Once you've opened your connection
//you can begin transmitting data to the server
//using the following method
ws.send("You\'re message");
}
So the main purpose of ws.send() method is to transmit data from the client to the server which is done by simply calling the WebSocket object's send() [in your case ws.send(msg)].
And also send data only takes place once a connection is established with the server by defining an onopen event handler.

Socket.IO subscribe to multiple channels

I want to build a simple chat room system on top of Socket.IO where user can create a new chat room and then people can start chatting.
This sound simple but as the Socket.IO 0.9.4 I'm running now, after reading a few SO posts together with the document on socket.io, i'm getting more and more confused. So, I hope that someone can provide me with instruction that WORK with 0.9.4:
I need a way to subscribe to a room. The room name is chosen by user. When a message is posted in a room, the user should receive it. How should I write the server code, how should I write the client code?
A user can join multiple rooms simultaneously.
I want another system to send a message to all user in a certain room. This 'another system' send the message through a request handled by express. How would I write that request handler?
This is all pretty straightforward with the socket.io rooms feature. Take a look at the documentation on LearnBoost wiki.
https://github.com/LearnBoost/socket.io/wiki/Rooms
It allows for being connected to multiple rooms over a single socket. I put together a quick test with the following code.
Server
io.sockets.on('connection', function(client){
client.on('subscribe', function(room) {
console.log('joining room', room);
client.join(room);
})
client.on('unsubscribe', function(room) {
console.log('leaving room', room);
client.leave(room);
})
client.on('send', function(data) {
console.log('sending message');
io.sockets.in(data.room).emit('message', data);
});
});
Client
var socket = io.connect();
socket.on('message', function (data) {
console.log(data);
});
socket.emit('subscribe', 'roomOne');
socket.emit('subscribe', 'roomTwo');
$('#send').click(function() {
var room = $('#room').val(),
message = $('#message').val();
socket.emit('send', { room: room, message: message });
});
Sending a message from an Express route is pretty simple as well.
app.post('/send/:room/', function(req, res) {
var room = req.params.room
message = req.body;
io.sockets.in(room).emit('message', { room: room, message: message });
res.end('message sent');
});

Resources