Currently I have facing issue that I got response to all users.
I want to just notify for Selected user in single chat module.
like below i want to sent notification to this "userid" only
Client side file code has below
var forwardString =
{
"userid": actual_receiverID,
"id": msgId
};
socket.emit('insertReceiverIdInMessageForwardReq',forwardString);
socket.on('insertReceiverIdInMessageForwardRes', function (messages) {
var updatedMsg = messages.Messages;
});
------------------Server Side code------------------
io.on('connection', function (socket) {
socket.on('insertReceiverIdInMessageForwardReq', function (status) {
io.emit('insertReceiverIdInMessageForwardRes', res);
});
});
// sending to individual socketid (private message)
socket.to(<socketid>).emit('hey', 'I just met you');
// or you can do this as well
io.sockets.connected[<socketid>].emit('hey', 'I just met you');
Please refer the documentation for more details: https://socket.io/docs/emit-cheatsheet/
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
Below is my Server side and client side file:
Server side file:
'use strict';
var model = require('../model/model.js');
class Socket{
constructor(socket){
this.io = socket;
this.users = [];
}
socketEvents(){
this.io.on('connection', (socket) => {
socket.on('username', (data) => {
this.users.push({
id : socket.id,
userName : data.username
});
let len = this.users.length;
len--;
model.addSocketId( data.username,this.users[len].id);
this.io.emit('userList',this.users,this.users[len].id);
});
socket.on('getMsg', (data) => {
model.insertMessages({
fromUserId: data.fromUserId,
toUserId: data.toUserId,
message: data.msg
});
console.log("socket id is:");
console.log(data.toid);
socket.broadcast.to(data.toid).emit('sendMsg',{
msg:data.msg,
name:data.name
});
});
socket.on('disconnect',()=>{
for(let i=0; i < this.users.length; i++){
if(this.users[i].id === socket.id){
this.users.splice(i,1);
}
}
this.io.emit('exit',this.users);
});
});
}
socketConfig(){
this.socketEvents();
}
}
module.exports = Socket;
Below is my Client Side File:
<script src="/socket.io/socket.io.js"></script>
<script type="text/javascript">
var socket = io.connect("http://192.168.1.12:3000");
socket.on('sendMsg', (data) => {
console.log("send message-list");
$('#message-list').append("<li class='friend-user'>"+data.msg+"</li>");
});
socket.on('userList', (completeUserList,userSocketId) => {
console.log('userlist function');
var userList = completeUserList;
});
$('document').ready(function(){
$(document).on('click', "#msg-btn", function (event) {
var messagePacket = {
toid: $("#friendSocketId").text(), //stored in hidden format from db
msg: $('#message').val(),
name: $("#myUserName").text(),
fromUserId: $("#loginUserId").text(),
toUserId: $("#friendUserId").text(),
};
socket.emit('getMsg',messagePacket);
});
</script>
In this, When user clicks on send button from front-end then "getMsg" event emitting successfully. getMsg function took receiver socket id as message and emit "sendMsg" event to particular socket id. But sendMsg event is not sending msg to particular socket id. please help.
It looks like you don't have a key called toid on data object. You might have mistyped it. Replace toid with toUserId and it should work.
Since you are sending a message to another socket, instead of a room, you can use socket.to().emit() instead of socket.broadcast.to().
From Socket.IO docs:
// a private message to another socket
socket.to(/* another socket id */).emit('hey');
So, replace socket.broadcast.to() with socket.to().emit(), like:
socket.to(data.toid).emit('sendMsg',{
msg:data.msg,
name:data.name
});
EDIT:
You asked the following question in the comments below this answer:
Does socket id changed automatically after
login when user send message or it remains same when client logged in?
Socket id is created for each client when io.connect() is executed.
In your code, this is the first line in your script file. So, a new socket id is created every time this script loads.
So, every time the page containing this script is loaded, a new socket id is created. If you refresh the page, this script loads again and a new socket id is created.
To answer your question, socket id remains same as long as user is on the same page. So, when a user sends a message it doesn't change, unless the user navigates to another page or refreshes this page after sending the message. So, if a user logs out and logs in, this page loads again, so socket id changes.
I think you are storing the socket id in database after user logs in, but are not updating it when user navigates to another page or logs out and logs in again. So, when you are emitting a message from server, you are sending it to user's previous socket id, not the current one.
I am trying to set up a chat interface on a site using nodejs.
I need to update the logged_in_user list after a user is authenticated.
I am using this code as a reference
https://github.com/amirrajan/nodejs-chat
io.sockets.on('connection', (socket) => {
socket.on('sendchat', (data) => {
io.sockets.emit('updatechat', socket.username, data);
});
As you can see on the 'connection' event the updatechat event is triggered.
In the client side (public/app.js),the chatlist is updated on getting the updatechat event.
I need to do the same but after a client is authenticated.
Can I somehow tweak the socket object to trigger the event on a 'login' event
This is my code
app.get('/authenticate',function(request,response)
{
var db = couch.db.use('users');
var email = request.query['email'];
var pass = request.query['password'];
db.get(email,{email:email},function(err,body){
if(err)
console.log(err);
else
{
var user_pass = body['password'];
var name = body['name'];
console.log(user_pass);
if(pass == user_pass)
{
eventEmitter.emit('login',name);
response.render('pages/dashboard',{user:body['name']});
}
}
});
// And on 'login' event
eventEmitter.on('login', function(name)
{
// ?????? Broadcast the new user to all logged in users to update the chatlist
});
I have tried to redirect the logged in users to another port and use the socket 'connection' event there.It sort of works but I want to know if there is another approach I could use.
You should use socket.io middleware for authentication.
io.use(function(socket,next){
//auth here
});
Take a look at the docs http://socket.io/docs/server-api/
You can get the req and res objects from the socket object being passed to the middleware.
Note, it is not a great idea to pass a password on the query since the url is not pass ssl.
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 tried to add new socket to some rooms in a middleware, but it seems not working while a first emit haven't be done for a socket(client side). When a socket (client side) send a 'message' event it will then work and be part of the room.
Is it a normal behavior?
Am I mandatory to join room in 'connection' event?
app.js (server side)
var app = require('http').createServer(function (req, res){
res.end('no rest');
});
var io = require('socket.io')(app);
app.listen(7076);
io.use(function(socket, next){
socket.join('toto');
next();
});
io.on('connection', function (socket) {
socket.on('message', function (data) {
socket.to('toto').emit('message', data);
});
});
According to the documentation, socket.to('toto').emit... syntax is not correct. You should use one of the following forms:
send everyone in "toto" room:
io.to('toto').emit('message', data);
send everyone in "toto" room except the sender:
socket.broadcast.to('toto').emit('message', data);
In fact the problem wasn't on the server side at all... It was my client that i didn't describe.
When clicked on a button to send a message here is the function called
function messageManagement(cb)
{
var message = $('#message_text').val();
if (!message || message.length == 0)
message = 'I am watching you';
socketClient.emit('message', {message:message});
socketClient.on('message', function (data){
console.log(data.messsage);
drawMessage(data);
});
}
As you can see each time the client emit a message it also register to the response event. So each time I emit a message a registered one more time to same event... It was messy so i changed this and it worked..