I want my client-side code to send the server the user's userid when establishing the connection, then i want the server to check the database for new messages for each user that is connecting, and send the user the number of new messages it has when new messages are available.
My client-side code:
var socket = io.connect('http://localhost:8000');
socket.on('connect', function () {
socket.emit('userid', '1');
});
socket.on('new_message', function (data) {
var number_of_messages= "<p>"+data.number+"</p>";
$('#container').html(number_of_messages);
});
My server-side code:
io.sockets.on( 'userid', function (data) {
console.log('userid: '+data);
});
My problem is that the above code is not working: the userid is never received by the serverside and the on('userid') is never called.
My question is how to know which socket sent this user id and how to send to only this specific socket a certain message.
I have solved the problem by saving the clients socket and their id into a global array. this is not a good solution but it works; I know there are rooms and namespaces but I never used it..
socket.io namespaces and rooms
however,
(I used express)
client:
var socket = io.connect('http://localhost:3000',{reconnection:false});
socket.once('connect', function() {
socket.emit('join', '#{id}');
};
server:
var clients = [];
app.io.on('connection', function(socket) {
socket.on('join', function(data) {
clients.push({
ws: socket,
id: data
});
//retrive the messages from db and loop the clients array
//and socket.send(things)
}
}
Related
The code below works fine by broadcasting typing notification and chat messages to all connected users.
Here is what I want: How do I send typing notification and chat messages only to users connected to a particular room
say Room1, Room2 etc.
here is the code
index.html
var socket = io();
var user = 'nancy';
function submitfunction(){
var from = 'nancy';
var message = 'hello Nancy';
socket.emit('chatMessage', from, message);
}
function notifyTyping() {
var user = 'nancy'
socket.emit('notifyUser', user);
}
socket.on('chatMessage', function(from, msg){
//sent message goes here
});
socket.on('notifyUser', function(user){
$('#notifyUser').text(nancy is typing ...');
setTimeout(function(){ $('#notifyUser').text(''); }, 10000);
});
server.js
var io = require('socket.io')(http);
io.on('connection', function(socket){
socket.on('chatMessage', function(from, msg){
io.emit('chatMessage', from, msg);
});
socket.on('notifyUser', function(user){
io.emit('notifyUser', user);
});
});
am using npm installed socket.io ^2.3.0
To send the message to a specific room, you will have to create and join a room with roomId. Below is a basic code snippet
//client side
const socket = io.connect();
socket.emit('create', 'room1');
// server side code
socket.on('create', function(room1) {
socket.join(room1);
});
To emit data to a specific room
// sending to all clients in 'room1'except sender
socket.to('room1').emit('event',data);
// sending to all clients in 'room1' room, including sender
io.in('room1').emit('event', 'data');
You can follow this question for details on how to create a room?
Creating Rooms in Socket.io
This emit cheat sheet might also be useful:
https://github.com/socketio/socket.io/blob/master/docs/emit.md
Scenario is i have a server where socket(1) runs i have one more server where socket(2) client connects to socket(1)
I have one browser socket which connects to socket(1)
Idea is to do request from browser and bring data from socket(2) server
Not sure how to difference between socket clients as all the sockets are similar to socket(1)
Ideally there will be multiple browser sockets and multiple socket(2) clients
Browser sockets can make request to any of the socket(2) clients
How to implement it using nodejs socket.io
Server
socket.on('action', (action) => {
if(action.type === 'server/hello'){
io.sockets.emit('broadcast',{ description: clients + ' clients connected!'});
console.log('Got hello data!', action.data);
}
});
Browser client
var socket = io.connect('localhost:3000', {reconnect: true});
socket.on('connect', function(data) {
socket.emit('joined', 'Hello World from client this is client plxx');
});
socket.on('response2', function(data) {
console.log("got it ", data);
$('#messages').append($('<li>').text(JSON.stringify(data)));
});
Server client
var io = require('socket.io-client');
var socket = io.connect('http://localhost:3000', {reconnect: true});
socket.on('broadcast', function (t) {
socket.emit("data", {data: 32})
console.log('broadcast! my host is est');
});
i should be able to communicate between socket clients
What I understood from your question is: you need to differentiate between sockets from different clients.
To solve that I would suggest simply emitting the socket source from the client on connect.
And on the server split the sockets into two lists.
Example:
Server
const BROWSER_CLIENTS = {};
const SERVER_CLIENTS = {};
io.on("connection", socket => {
socket.on("source", payload => {
if (payload == "browser")
BROWSER_CLIENTS[socket.id] = socket;
else if (payload == "server")
SERVER_CLIENTS[socket.id] = socket;
});
socket.on("disconnect", () => {
delete BROWSER_CLIENTS[socket.id];
delete SERVER_CLIENTS[socket.id];
});
});
Browser Client
socket.on("connect", () => {
socket.emit("source", "browser");
});
Server Client
socket.on("connect", () => {
socket.emit("source", "server");
});
Now when you receive an event you can detect from which source it originated. And if you need to send to all sockets of one type of clients you can simply do this:
Server
for (let i in BROWSER_CLIENTS)
BROWSER_CLIENTS[i].emit("Hello Browsers")
for (let i in SERVER_CLIENTS)
SERVER_CLIENTS[i].emit("Hello Servers")
EDIT: I found this link and thought you could make use of it. Socket.io Rooms
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);
});
Is there a way to set up socket.io listeners for certain clients after they execute a command? For example:
socket.on('setupServer', function (data) {
console.log("setupServer called");
// Now set up listeners
socket.on('serverAction', function (data) {
console.log('Listener for clients calling setupServer');
});
});
In the above, a client has connected and has issued a 'setupServer' command to the node.js server. The server now listens for 'serverAction' from the specific client. Other clients won't be able to use 'serverAction' without calling 'setupServer' first.
You could create a room and validate some data from user and then join those users to that room, after that emit some events to that users in that room.
Something like this.
server.js
var io = require('socket.io')(server);
io.on('connection',function(socket){
socket.emit('auth_user')
socket.on('response_from_user',function(data){
if(data.name === "Blashadow"){
//join that user to the room
socket.join('/room',function(){
//emit some custom event to users in that room
io.in('/room').emit('custom_event_room', { info: 'new used connected from room' });
});
}
});
});
client.html
var socket = io('localhost');
socket.on('auth_user', function (data) {
socket.emit('response_from_user', { name : "Blashadow" });
});
socket.on('custom_event_room',function(data){
console.log(data);
});
I'm using the Twit library for Node.js, and I begin by creating a stream of incoming tweets here:
var stream = T.stream('statuses/filter', { locations: allLocations })
Then, using Socket.io, I send the tweets to each connected client, and also log when a user disconnects:
io.on('connection', function(socket){
socket.on('disconnect', function() {
console.log("User disconnected!!!!!");
});
stream.on('tweet', function(tweet) {
// sends tweet to client in question:
socket.emit('info', tweet);
});
}
The problem is that even after a user disconnects, the tweets meant for them still keep getting parsed by the event listener, and logged to the console. Is there a way to "disable" all socket-related event listeners when the user disconnects? Or is there a cleaner way to handle this situation with streaming tweets?
Here's one solution:
io.on('connection', function(socket){
socket.on('disconnect', function() {
console.log("User disconnected!!!!!");
stream.removeListener('tweet', onTweet);
});
function onTweet(tweet) {
// sends tweet to client in question:
socket.emit('info', tweet);
}
stream.on('tweet', onTweet);
}
Also, you could just broadcast to all sockets using a single 'tweet' event handler instead of adding a new 'tweet' event handler for every connection.