I have yet to figure out how to directly respond to only the sender using socket.io
I have learned that io.sockets.emit sends to all clients but I wont to send information back to the sender.
code:
socket.on('login', function (data) {
db.users.find({username: cc.lowerCase(data.username)}, function(err, users) {
if (users.length > 0) {
users.forEach( function(user) {
console.log(user.length);
if (user.password == data.password) {
io.sockets.emit('login', { username: user.username });
} else {
io.sockets.emit('error', { message: "Wrong username or password!" });
}
});
} else {
io.sockets.emit('error', { message: "Wrong username or password!" });
}
});
});
When your server listens, you usually get a socket at the "connection" event :
require('socket.io').on('connect', function(socket){
A socket connects 2 points : the client and the server. When you emit on this socket, you emit to this specific client.
Example :
var io = require('socket.io');
io.on('connect', function(socket){
socket.on('A', function(something){
// we just received a message
// let's respond to *that* client :
socket.emit('B', somethingElse);
});
});
Be careful that those are two different calls :
socket.emit : emit to just one socket
io.sockets.emit : emit to all sockets
Simple example
The syntax is confusing in socketio. Also, every socket is automatically connected to their own room with the id socket.id (this is how private chat works in socketio, they use rooms).
Send to the sender and noone else
socket.emit('hello', msg);
Send to everyone including the sender(if the sender is in the room) in the room "my room"
io.to('my room').emit('hello', msg);
Send to everyone except the sender(if the sender is in the room) in the room "my room"
socket.broadcast.to('my room').emit('hello', msg);
Send to everyone in every room, including the sender
io.emit('hello', msg); // short version
io.sockets.emit('hello', msg);
Send to specific socket only (private chat)
socket.broadcast.to(otherSocket.id).emit('hello', msg);
late but better than never ;)
I had smth like this:
io.on('connection', function(socket){
socket.emit('some event', data);
socket.on('private event', function(message){
this.emit('other private event', message);
}
}
After some testing, I realized that 'this.emit' inside 'private event' closure send back only to sender. So i tried 'this.broadcast.emit', which send the message to all connected except the sender. I believe this is what you want from your code.
Related
After the client emits a message to the server, I'm trying to emit that message to every other client in the room, however the original client who sent the message also receives the emit... This seems to go completely against all documentation I've read. My code is as follows:
socket.on('slots', (slots) => {
console.log(socket.id);
const [thisRoom] = socket.rooms;
console.log(thisRoom);
socket.to(thisRoom).emit('slots', slots);
});
I'm using socket.io 4.5.3.
Many thanks.
Check this answer Send a response to all clients except the sender
// sending to all clients except sender
socket.broadcast.emit('message', "this is a test");
Please note that broadcasting is a server-only feature.
Therefore you need to configure this in the server.
io.on('connection', (socket) => {
socket.on('chat message', msg => {
socket.broadcast.emit('chat message', msg);
});
});
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
I am using socket.io 1.4.0.
I am trying to send a message to put the client in a room called 'myroom', then send a message to the room from the client and then get the response from the room. However I get no response from using
socket.to('myroom').emit('message', 'what is going on, party people?');
Here is my client code:
socket.on('connect', function() {
// Connected, join the booking room for to receive messages for this room
socket.emit('room', 'myroom');
});
socket.on('message', function(msg){
console.log('message: ' + msg);
});
socket.emit('booking room message', {roomid: 'myroom', message: 'hello'});
Here is my server code:
// Set up the Socket.IO server
var io = require("socket.io")(server)
.use(function(socket, next) {
// Wrap the express middleware
sessionMiddleware(socket.request, {}, next);
})
.on("connection", function(socket) {
console.log(socket.request.session);
if (socket.request.session.passport) {
var userId = socket.request.session.passport.user;
//Sign up client for the room from client side.
socket.on('room', function(room) {
socket.join(room);
console.log(userId + ' has joined booking room: ' + room);
});
//make a room for this user
socket.join(userId);
console.log("User ID: " + userId + " connected. socketID: " + socket.id);
socket.on('disconnect', function() {
console.log("User ID: " + userId + " disconnected.");
});
socket.on('booking room message', function(data) {
console.log('message sent from browser to a room');
console.log(data);
socket.to('myroom').emit('message', 'what is going on, party people?');
});
}
});
I get a message back from the server as expected when I use :
socket.emit('message', 'what is going on, party people?');
So there is something wierd going on with the join room function. A couple of things to note, I have some middleware tha gets the ID from express - dont think that is having any impact. Also I create a seperate room for the userID.
Can a user be in two rooms at once? I am not sure what is causing this.
Thanks,
it seemed that neither to or in will send the response back to the same client. The code above did send to other clients in the room however.
I'm making an application for our website where users can send chat messages with each other. I've managed to do this successfully using nodejs and socketio. I have a header with some sort of notification icon just like facebook that can be seen in all the pages. Now if the user opens multiple tabs and he receives a message, then all open tabs should see the icon light up. I've gotten this to work by tracking the socket connections opened by users through a 2D array of sockets:
var container = {};
io.sockets.on( 'connection', function(client) {
client.on('set account online', function(username) {
if (!(username in container)) {
console.log(username + " is now Online" );
container[username] = [];
}
client.username = username;
container[username].push(client);
});
client.on('set account offline', function(username) {
if (username in container) {
delete container[username];
console.log(username + " is now Offline" );
}
});
And then when a message is sent I iterate through the appropriate array element
client.on('send message', function(data) {
if (data.recipient in container) {
var clients = container[data.recipient];
for(var i = 0; i < clients.length;i++){
clients[i].emit('send message', {recipient: data.recipient, message: data.message });
}
}
});
That's working well and all (not sure how well coded it is though). The problem is if the user closes a tab, the socket for that tab still exists in the container variable and node would still try to emit to that socket if a message is received for that particular user. Also it just feels cleaner to un-track any disconnected socket.
I've been thinking about this and I think I have to tie the socket disconnect event to the client side's onbeforeunload event and we all know how that performs across different browsers. Any suggestion regarding what's the proper way to splice off disconnected sockets from the container array?
As per my comment:
You should really be implementing rooms. On each connection each user
should join their own room, any additional connections from the same
user should join this room. You can then emit data to the room and
each client inside it will receive the data.
Your code can be changed to:
io.sockets.on('connection', function(client) {
client.on('set account online', function(username) {
client.join(username);
});
client.on('set account offline', function(username) {
client.leave(username);
});
client.on('send message', function(data) {
io.to(data.recipient).emit('send message', {
recipient: data.recipient,
message: data.message
});
});
});
I'm having trouble getting basic client to client (or really client->server->client) working with socket.io. Heres the code I have right now:
io.sockets.on('connection', function (socket) {
users.push(socket.sessionId);
for(userID in users) {
console.log(userID);
io.sockets.socket(userID).emit('message', { msg: 'New User Connected succesfully' });
}
socket.emit('message', { msg: 'Connected succesfully' });
socket.on('my other event', function (data) {
console.log(data);
});
});
From my understanding, that should send the new user message to every connected user (individually, since i want to do actual individual messages later). Instead, I only get the 'connected successfully' message at the end. I don't get any errors or other negative indicators from my server or client.
Any ideas of why io.sockets.socket(userID).emit() doesn't work or what to use in its place?
Socket.io has the concept of rooms where, once a socket has joined a room, it will receive all message sent to a room, so you don't need to track who's in the room, deal with disconnections, etc...
On connection, you'd use:
socket.join('room')
And to send a message to everyone in that room:
io.sockets.in('room').emit('event_name', data)
More info on the socket.io wiki: https://github.com/LearnBoost/socket.io/wiki/Rooms
Try
users.push(socket); // without .sessionId
for (var u in users) {
// users[u] is now the socket
console.log(users[u].id);
users[u].emit('message', { msg: 'New User Connected succesfully' });
}
You can now also use ...
io.to('room').emit('event_name', data);
as an alternative to io.sockets.in