Socket.io broadcast to not working - node.js

I have the following code:
var room = "1";
var chat = io.connect("localhost:3700/");
self.chat = chat;
chat.on("connection", function(socket){
socket.emit("room", room);
socket.on('message', function (data) {
self.receiveMessage(data);
});
});
chat.broadcast.to(room).emit('send',"HEllo");
receiveMessage:
receiveMessage: function(data){
var $elem = $("#chat1");
var $content = $elem.find(".messageText");
if(data.message) {
messages.push(data);
var html = '';
for(var i=0; i<messages.length; i++) {
html += '<b>' + (messages[i].username ? messages[i].username : 'Server') + ': </b>';
html += messages[i].message + '<br />';
}
$content.html(html);
} else {
console.log("There is a problem:", data);
}
}
The line chat.broadcast.to(room).emit('send',"HEllo"); gives me the error:
Uncaught TypeError: Cannot call method 'to' of undefined
What am I doing wrong?

Not really sure but I think you can send a broadcast only on connection.
You can try this:
var room = "1";
var chat = io.connect("localhost:3700/");
self.chat = chat;
chat.on("connection", function(socket){
socket.emit("room", room);
socket.on('message', function (data) {
self.receiveMessage(data);
});
chat.broadcast.to(room).emit('send',"HEllo");
});
Of course you can also send the broadcast in a separate handler, i.e.:
var room = "1";
var chat = io.connect("localhost:3700/");
self.chat = chat;
chat.on("connection", function(socket){
socket.emit("room", room);
socket.on('message', function (data) {
self.receiveMessage(data);
});
socket.on('foo event', function(data) {
chat.broadcast.to(room).emit('send',"HEllo");
}
});

Related

How do I pass socket.io room name from one client to another?

I'm using socket.io v4 with NodeJS (Express).
So, the situation that I have is that I have a chat window for client and the client can enter their email and message. Now, I want to create a room based on that email and have another client join that room. My current implementation doesn't work. It creates the room but the other client is unable to join it.
Server Side Code:
io.of(/^\/dynamic-[a-zA-Z0-9]+$/).on("connection", (socket) => {
let email;
const namespace = socket.nsp.name;
let namespaceToCheck = namespace.split('-');
//console.log(namespaceToCheck[1])
User.findOne({apiKey: namespaceToCheck[1]})
.then((doc)=> {
if(namespaceToCheck[1] == doc.apiKey) {
socket.once("pass-email", (data) => {
io.of(namespace).emit("pass-email", data);
email = data;
})
console.log("Valid Connection");
socket.on("chat-message", (msg) => {
socket.join(email, function(){
//console.log(`Socket now in ${socket.rooms}`);
});
//console.log(msg);
console.log(socket.rooms);
Message.findOne({namespace: namespace})
.then((doc) => {
// console.log(doc);
doc.messages.push(msg);
doc.save().then((saved) => { return Promise.resolve(saved) });
})
// console.log(socket.handshake);
//io.of(namespace).sockets.in(data).emit("chat-message", msg);
console.log(email);
io.of(namespace).to(email).emit("chat-message", msg);
})
}
})
.catch((err)=> {
console.log(err);
})
});
Client Socket Code (from which I'm passing the email)
var chatSocket = io("http://localhost:3000/dynamic-8171d2a713d65c5edf81e45af4d14558a2c62275df05c73ca198a94d422e5948");
var chatBtn = document.querySelector('.chat-btn');
var input = document.querySelector('.chat-input');
var messages = document.querySelector(".messages");
var emailInputTag = document.querySelector(".email-input");
input.addEventListener("keypress", function(event) {
if (event.key === "Enter") {
event.preventDefault();
if (input.value && emailInputTag.value) {
chatSocket.emit('create-room', emailInputTag.value);
//chatSocket.join(emailInputTag.value)
chatSocket.emit('chat-message', emailInputTag.value + ':' + input.value);
input.value = '';
}
}
});
chatBtn.addEventListener('click', function(e) {
e.preventDefault();
if (input.value && emailInputTag.value) {
chatSocket.emit('chat-message', emailInputTag.value + ':' + input.value);
input.value = '';
}
});
chatSocket.on('chat-message', function(msg) {
var item = document.createElement('div');
item.classList.add('msg');
item.textContent = msg;
messages.appendChild(item);
window.scrollTo(0, document.body.scrollHeight);
});
This is the rooms that this socket is in:
Client chat socket code (from which I want to receive room event and join the received room)
var chatSocket = io(`http://localhost:3000/dynamic-${ApiKey}`);
chatSocket.on("connect", function () {
console.log("Connected-test-succeeded");
// Connected, let's sign-up for to receive messages for this room
});
chatSocket.on("pass-email", (val) => {
console.log(val);
console.log("Listening");
});
var chatBtn = document.querySelector(".chat-btn");
var input = document.querySelector(".chat-input");
var messages = document.querySelector(".messages");
input.addEventListener("keypress", function (event) {
if (event.key === "Enter") {
event.preventDefault();
if (input.value) {
chatSocket.emit();
chatSocket.emit(
"chat-message",
"Owner" + ":" + input.value
);
input.value = "";
}
}
});
chatBtn.addEventListener("click", function (e) {
e.preventDefault();
if (input.value) {
chatSocket.emit(
"chat-message",
"Owner" + ":" + input.value
);
input.value = "";
}
});
chatSocket.on("chat-message", function (msg) {
console.log("Message received: " + msg);
var item = document.createElement("div");
item.classList.add("msg");
item.textContent = msg;
messages.appendChild(item);
window.scrollTo(0, document.body.scrollHeight);
});
P.S: I know that the code is a bit messy but what I'm trying to do here is making a tawk.to clone so different namespace for each website url and the rooms are different in the said namespace for different users.

NodeJS - socket.broadcast.to not emitting inside nested listeners

I'm trying to emit messsage to specific rooms, once the "joinedRoom' listener is triggered by the client, the code works fine if I place my code outside the joinedRoom listeners, otherwise it does nothing.
Code:
app.get('/room/:room/user/:user', function(req, res){
var room = {
username: req.params.user,
roomname: req.params.room
};
res.render('room', room);
});
var users = {};
io.sockets.on('connection', function (socket) {
socket.on('joinedRoom', function(roomData){
socket.username = roomData.username;
socket.room = roomData.roomname;
console.log("Roomname: " + socket.room);
console.log("Username: " + socket.username);
socket.join(socket.room);
socket.broadcast.to(socket.room).emit('newUser', socket.username);
socket.on('disconnect', function(){
socket.broadcast.emit('userLeft', socket.username);
socket.leave(socket.room);
console.log('Connection id: ' + socket.id);
});
});
});
I saw the docs and some sample code it everything seeems to be correct (when it comes simply to syntax) am I missing something simple here?
Thanks!
EDIT
Client code:
var socket, roomname, ioRoom;
var socket = io.connect('http://localhost:3000');
socket.on('enterRoom', function(roomname){
console.log("ENTERED ROOM: " + roomname);
});
socket.on('newUser', function(username){
pushUserName(username);
pushUserStatus(username, ' has joined the room <br/>')
});
socket.on('newRoom', function(data){
alert(data)
});
socket.on('userLeft', function(username){
pushUserStatus(username, ' has left the room <br/>')
})
function pushUserName(username){
var el = document.getElementById("username");
el.innerHTML += username + '<br/>';
}
function pushUserStatus(username, message){
var el = document.getElementById("joined");
el.innerHTML += username + message;
}

I get length 1 even It didn't connect to socket

let app = require('express')(),
http = require('http').Server(app),
User = require('../models/users');
http.listen(8080, function () {
console.log('Socket IO server has been started on port 8080');
});
let io = require('socket.io')(http);
var socketRoom = {};
io.of('/chat').on('connection', function (socket) {
var ioRooms = io.of('/chat').adapter.rooms;
console.log(ioRooms) // I got length 1 when I print it.
socket.on('requestRandomChat', function (data) {
User.findOne({userToken : data.userToken}, function(err, user){
if(err) socket.emit('db error');
if(!user) socket.emit('db error : user not found');
else {
socket.emit('responseUserProfile', user);
for (var key in rooms){
if (key == ''){
continue;
}
if (rooms[key].length == 1){
var roomKey = key.replace('/', '');
socket.join(roomKey);
io.sockets.in(roomKey).emit('completeMatch', {});
socketRoom[socket.id] = roomKey;
return;
}
}
socket.join(user.userToken);
socketRoom[user.userToken] = socket.userToken;
}
});
});
socket.on('cancelRequest', function (data) {
socket.leave(socketRoom[socket.id]);
console.log(ioRooms);
});
socket.on('sendMessage', function (data) {
console.log(ioRooms);
console.log('sendMessage!');
io.of('/chat').in(socketRoom[socket.id]).emit('receiveMessage', data);
});
socket.on('disconnect', function (data) {
console.log(ioRooms);
var key = socketRoom[socket.id];
socket.leave(key);
io.of('/chat').in(key).emit('disconnect');
var clients = io.of('/chat').clients(key);
for (var i = 0; i < clients.length; i++) {
clients[i].leave(key);
}
});
});
when I trying to get a length of rooms, I get a length 1 with a socketId.
but I've never connected to the room. Is that default room? can somebody explain what's happening with the room socket?
//{ '/chat#2HAMaavywIwZ1B5fAAAD': Room { sockets: {
'/chat#2HAMaavywIwZ1B5fAAAD': true }, length: 1 } }
In socket io each socket is automatically connected to a default room identified by socket ID.
That's why you get length 1.
I hope you find it helpful.
http://socket.io/docs/rooms-and-namespaces/

Nodejs - data transfer between server and client

I was given a task to send JSON string from client to server and from server to client, whenever there is a new record found to send.
I decided to build TCP connection(suggest me if there is any other better way in Node.js) between server and client to transfer data.
The problem is, I was supposed to use a delimiter to separate JSON strings one from another. I am afraid what if the json string contains the delimiter string inside the object. I am looking for a better way to separate two JSON strings.
Below is my code. Please help me.
Client
var net = require('net')
, client = new net.Socket();
var chunk = ''
, dlim_index = -1
, delimit = '~~';
client.connect(config.Port, config.IpAddress, function () {
console.log('Server Connected');
client.write('CLIENTID:' + process.argv[2]);
client.write(delimit);
});
client.on('data', function (data) {
var recvData = data.toString().trim();
chunk += recvData;
dlim_index = chunk.indexOf(recvData);
console.log(data);
while (dlim_index > -1) {
var useData = chunk.substring(0, dlim_index);
if (useData == 'SUCCESS') {
controller.listenOutQueue(function (dataToSend) {
var object = JSON.parse(dataToSend);
client.write(dataToSend);
client.write(delimit);
});
}
else {
var record = JSON.parse(useData);
controller.insertIntoQueue(record, function (status) {
});
}
chunk = chunk.substring(dlim_index + 2);
dlim_index = chunk.indexOf(delimit);
}
});
client.on('close', function () {
console.log('Connection closed');
});
client.setTimeout(50000, function () {
//client.destroy();
});
Server
var net = require('net')
, server = net.createServer()
, delimit = '~~'
, clients = [];
controller.listenOutQueue(function (dataToSend) {
client.write(dataToSend);
client.write(delimit);
});
server.on('connection', function (socket) {
var chunk = '';
var dlim_index = -1;
socket.on('data', function (data) {
var recvData = data.toString().trim();
chunk += recvData;
dlim_index = chunk.indexOf(delimit);
while (dlim_index > -1) {
var useData = chunk.substring(0, dlim_index);
if (useData.substring(0, 9) == 'CLIENTID:') {
socket.clientid = useData.replace('CLIENTID:', '');
console.log('Client Id: ' + socket.clientid);
clients.push(socket);
var successMessage = "SUCCESS";
socket.write(successMessage);
socket.write(delimit);
}
else {
controller.insertIntoQueue(JSON.parse(useData), function (status) {
});
}
chunk = chunk.substring(dlim_index + 2);
dlim_index = chunk.indexOf(delimit);
}
});
socket.on('end', function () {
console.log('Connection Closed (' + socket.clientid + ')');
});
socket.on('error', function (err) {
console.log('SOCKET ERROR:', err);
});
});
server.listen(config.Port, config.IpAddress);

How to create online users list using webrtc and nodejs on the server end

I am using webrtc to make a audio, video and chat application where I need keep all the users in a user list in the serverside. Need help how to get this done.
Also, how can I remove users from the list when they logout from the system.
Need help to implement this.
webRTC.rtc.on('connect', function(rtc) {
//Client connected
});
webRTC.rtc.on('send answer', function(rtc) {
//answer sent
});
webRTC.rtc.on('disconnect', function(rtc) {
//Client disconnect
//console.log(webRTC);
});
webRTC.rtc.on('chat_msg', function(data, socket) {
var roomList = webRTC.rtc.rooms[data.room] || [];
for (var i = 0; i < roomList.length; i++) {
var socketId = roomList[i];
if (socketId !== socket.id) {
var soc = webRTC.rtc.getSocket(socketId);
if (soc) {
soc.send(JSON.stringify({
"eventName": "receive_chat_msg",
"data": {
"messages": data.messages,
"id": data.id,
"from": data.from,
"status": data.status,
"email": data.email
}
}), function(error) {
if (error) {
console.log(error);
}
});
}
}
}
});
As I was using webrtc.io module, so below are the methods that helped me to create the userlist and maintain the presence.
webRTC.rtc.on('join_room', function(data, socket) {
// Will get info who joined along with his socket id
}
And
webRTC.rtc.on('room_leave', function(room, socketid) {
// Will get info who left the room
}
Node.js code:
var users = {};
io.sockets.on('connection', function (socket) {
socket.emit('connect', true);
socket.on('message', function (data) {
socket.broadcast.emit('message', data);
});
socket.on('new-user', function (username) {
users[username] = username;
});
socket.on('check-presence', function (username) {
var isUserPresent = !! users[username];
socket.emit('presence', isUserPresent);
});
socket.on('remove-user', function (username) {
var user = users[username];
if (user) delete users[username];
});
});
This may also work (node.js):
var users = {};
io.sockets.on('connection', function (socket) {
var UserName;
socket.emit('connect', true);
socket.on('message', function (data) {
socket.broadcast.emit('message', data);
});
socket.on('new-user', function (username) {
users[username] = username;
UserName = username;
});
socket.on('check-presence', function (username) {
var isUserPresent = !! users[username];
socket.emit('presence', isUserPresent);
});
// removing user on "disconnect"
socket.on('disconnect', function () {
var user = users[UserName];
if (user) delete users[UserName];
});
});
For 1st case; client-side code:
var socket = io.connect();
socket.on('connect', function () {
socket.emit('new-user', 'username');
});
function removeUser() {
socket.emit('remove-user', 'username');
}
window.onbeforeunload = function () {
removeUser();
};
// if someone pressed "F5" key to refresh the page
window.onkeyup = function (e) {
if (e.keyCode == 116)
removeUser();
};
// if someone leaves via <a href>
var anchors = document.querySelectorAll('a'),
length = anchors.length;
for (var i = 0; i < length; i++) {
var a = anchors[i];
if (a.href.indexOf('#') !== 0 && a.getAttribute('target') != '_blank')
a.onclick = function () {
removeUser();
};
}
For 2nd case; client side code:
var socket = io.connect();
socket.on('connect', function () {
socket.emit('new-user', 'username');
});
You can check presence too:
socket.on('presence', isUserPresent) {
// boolean: user is present or not
});
socket.emit('check-presence', 'username');

Resources