Message broadcasted multiple times in Socket.io - node.js

I am relatively new to node.js and socket.io. While building a sample chat room application I am encountering a case where when I refresh the browser n times, and then send a message, the message gets broadcasted n-times to all the clients. How do I make it not broadcast multiple times and just once? Here goes the server side and client side code.
qaserver.js
var express = require('express')
, app = express()
, http = require('http')
, server = http.createServer(app)
, io = require('socket.io').listen(server, { log : false });
server.listen(4040);
var redis = require('redis');
var r43 = redis.createClient('6379', '127.0.0.1');
r43.select("43");
// Set the view directory to /views
app.set("views", __dirname + "/views");
app.use(express.static(__dirname + '/public'));
// Let's use the Jade templating language
app.set("view engine", "jade");
app.get("/", function(request, response) {
response.end("Welcome to the homepage!");
});
app.get("/qaclient", function(request, response) {
response.render("qaclient", { message: "Welcome to QA Forum" });
io.sockets.once('connection', function (socket) {
// when the client emits 'adduser', this listens and executes
socket.on('adduser', function(){
// store the username in the socket session for this client
socket.join('test_room');
socket.room='test_room';
console.log("------------- List of connected clients on adduser -------------------");
var clients = io.sockets.clients('test_room'); //
console.log(clients);
//socket.username = username;
socket.emit("welcome_fn",socket.room);
// echo to client they've connected
});
socket.on('message', function (data) {
//io.sockets.in(socket.room).emit('broadcast_message', data.name,data.message);
console.log("------------- List of connected clients on message broadcast -------------------");
var clients = io.sockets.clients('test_room'); //
console.log(clients);
socket.broadcast.to('test_room').emit('broadcast_message', data.name,data.message);
//io.sockets.emit('broadcast_message', data.name,data.message);
console.log(data.name);
console.log(data.message);
});
// when the user disconnects.. perform this
socket.on('disconnect', function(){
// remove the username from global usernames list
console.log('Socket disconnected : ');
console.log(socket.room);
socket.leave('test_room');
//console.log(socket.leave(socket.room));
});
});
});
--
qaclient.js
window.onload = function() {
var messages = [];
var field = document.getElementById("message");
sendButton = document.getElementById("sendbutton");
//var content = document.getElementById("content");
var name = document.getElementById("name");
var socket = io.connect('http://localhost:4040');
// on connection to server, ask for user's name with an anonymous callback
socket.on('connect', function(){
// call the server-side function 'adduser' and send one parameter (value of prompt)
socket.emit('adduser');
});
socket.on('welcome_fn',function(room)
{
chatcontent.innerHTML = "<b>Welcome to Chat central.. Type your message to start chatting in room "+ room +"</b>";
});
socket.on('broadcast_message', function (name,message) {
var data=new Object();
data.message=message;
data.username=name;
if(message) {
messages.push(data);
var html = '';
console.log(messages.length);
for(var i=0; i<messages.length; i++) {
html += '<b>' + messages[i].username + ': </b>';
html += messages[i].message + '<br />';
}
chatcontent.innerHTML = html;
}
//socket.emit('message', { name: name; message:field });
});
sendButton.onclick = function() {
if($.trim(field.value)=="")
{
alert("Enter the message Foo!");
}
else
{
name_tosend_tmp=name.value;
name_tosend= name_tosend_tmp.replace(/(<([^>]+)>)/ig,"");
message_tosend_tmp=field.value;
message_tosend= message_tosend_tmp.replace(/(<([^>]+)>)/ig,"");
socket.emit('message', { name: name_tosend , message:message_tosend });
var data=new Object();
data.message=message_tosend;
data.username=name_tosend;
messages.push(data);
var html = '';
for(var i=0; i<messages.length; i++) {
html += '<b>' + messages[i].username + ': </b>';
html += messages[i].message + '<br />';
}
chatcontent.innerHTML = html;
document.getElementById("name").value="";
document.getElementById("message").value="";
}
}
}

Related

How do I get the IDs of connected peers?

I managed to get the number of peers connected in my console log by having the console print out "You are peer number n" for each new connected peer.
Is there a way of adding the id of each connected peer too?
I'm relatively new with socket.io and I can't seem to find a way to do this.
This is my server.js file:
var app = require("express")();
var express = require("express");
var server = require("http").Server(app);
var p2pserver = require("socket.io-p2p-server").Server;
var io = require("socket.io")(server);
var ss = require("socket.io-stream");
var path = require("path");
app.use(express.static(__dirname));
io.use(p2pserver);
var peerNum = 0;
io.on("connection", function(socket) {
console.log("Peer " + peerNum + " connected");
io.emit("peer-num", peerNum);
peerNum++;
ss(socket).on("file", function(stream, data) {
var filename = path.basename(data.name);
var parts = [];
stream.on("data", function(data) {
parts.push(data);
});
stream.on("end", function() {
socket.broadcast.emit("file", parts);
});
});
});
server.listen(8080, function () {
console.log("Listening on 8080")
});
This is my client.js file:
// Browserified
var P2P = require("socket.io-p2p");
var io = require("socket.io-client");
var ss = require("socket.io-stream");
var socket = io();
var opts = {autoUpgrade: true, peerOpts: {numClients: 10}};
var p2p = new P2P(socket, opts);
var $ = require("jquery");
p2p.on("peer-num", function(num) {
console.log("You are peer number " + num);
$(".peerNum").html( "Number " + num );
});
p2p.on("file", function(stream) {
console.log(stream);
var img = document.createElement("img");
img.src = (window.URL || window.webkitURL).createObjectURL(new Blob(stream));
document.getElementById("receivedImages").appendChild(img);
});
$(function() {
$("#file").change(function(e) {
ss.forceBase64 = true;
var file = e.target.files[0];
var stream = ss.createStream();
ss(socket).emit("file", stream, {size: file.size,name:file.name});
var blobStream = ss.createBlobReadStream(file);
var size = 0;
blobStream.on("data", function(chunk) {
size += chunk.length;
console.log(Math.floor(size / file.size * 100) + "%");
});
blobStream.pipe(stream);
});
});
If what you mean by id is the internal id that socket.io assigns to a connection (on the server), then you can access that with socket.id. So, if you want to just use socket.id instead of your peerNum, variable, then you would change this:
io.emit("peer-num", peerNum);
to this:
io.emit("peer-num", socket.id);
The socket.id value is used only on the server. It is not meant to be a human readable moniker (it contains randomly generated characters), but it can be used to reference any given connection. Since its a string, it can be easily sent to other clients who can then use it when sending messages back to the server to reference particular client connections.

private chat with socket.io

I'm having trouble with my chat app, I need to be able to send a private message to a specific user, I was able to select that specific user but for some reason couldn't figure out how to send the private message.
Below you will find the code for my server, please help:
var express = require('express');
var app = express();
var PORT = process.env.PORT || 8000;
var http = require('http').Server(app); // this is a node server that uses express as the boiler plate
var io = require('socket.io')(http); // socket! pass our server as a parameter to it
// use express static to expose a folder
app.use(express.static(__dirname + '/public'));
var users = [],
connections = [];
var onlineClients = {};
// Register events on socket connection
io.on('connection', function(socket){
connections.push(socket);
// console.log("connected socket", connections);
socket.on("disconnect", function() {
users.splice(users.indexOf(socket.username), 1);
updateUsernames();
connections.splice(connections.indexOf(socket), 1);
console.log("disconnected socket", connections.length)
});
socket.on("send message", function(data) {
// console.log(data);
io.emit("new message", {msg: data, user: socket.username});
});
socket.on("notify user", function(data) {
io.emit("notify user", {user: socket.username})
});
socket.on("new user", function(data) {
socket.username = data;
users.push(socket.username);
updateUsernames();
});
function updateUsernames() {
io.emit("get users", users);
};
socket.on("private", function(data, recipientName) {
var recipient = connections.filter(function (recipient) {
return recipient.username === recipientName;
})[0];
console.log(recipient.id);
console.log(data);
io.sockets.socket(recipient.id).emit("received private msg", data);
});
// socket.on("create room", function(room) {
// socket.join(room);
// io.sockets.in(room).emit('event', "hey wusup am in this room");
// console.log(socket);
// })
});
http.listen(PORT, function(){
console.log('Server started on port ' + PORT);
});
First add user in chat room so that will easy to find a user in your private chat room
Your client side code for join private room
<input type="text" class="form-control" id="user_email" placeholder="user_email" />
<button text="join room" class="btn btn-primary btn-block" onclick="a();"> Join Room</button>
your javascript code in client side
function a(){
io.emit('privatechatroom', {email:document.getElementById('user_email').value});
}
your server side code to add user in your room
socket.on('privatechatroom',function(data){
socket.join(data.email);
io.emit('res',{mes:"you are added"})
});
now u can send private message to that person that is recently addedd to this room
client side
function b() {
io.emit('sendmail', { email: document.getElementById('sender_mail').value, message: document.getElementById('message').value });
$('#message').val('');
}
/*serverside code*/
socket.on('sendmail', function (data) {
io.sockets.in(data.email).emit('new_msg', { msg: data.message });
console.log(data.email);
});
Here is the clear solution of mine for your question...
Send a message to Particular client(Private chat)
I hope it will work for you sue..

Node Server not working with SSL

I have a node server code on named server.js
var env = require('dotenv').config({path: '../.env'});
var fs = require("fs");
var options = {
key: fs.readFileSync(env.APP_SSL_PATH + 'server.key').toString(),
cert: fs.readFileSync(env.APP_SSL_PATH + 'server.crt').toString()
};
var app = require('express')();
var http = require('https');
var server = http.createServer(options, app);
var io = require('socket.io')(server);
var redis = require('redis');
// Check if server is listening on its port
server.listen(env.APP_NODE_PORT, function() {
console.log('Listening on your port');
io.on('connection', function (socket) {
console.log("new client connected");
var redisClient = redis.createClient();
redisClient.subscribe('notification-channel', function(err, count) {
});
redisClient.on("message", function(channel, message) {
console.log( " message= "+ message + " channel = " + channel);
socket.emit(channel, message);
});
socket.on('disconnect', function() {
redisClient.quit();
});
});
});
Using http it works fine but then when I add the SSL certificate on https the code is not working already and it doesn't throw any error. I run the node server.js by
node server.js > stdout.txt 2> stderr.txt
there are no error log showing on stderr.txt file. Please help me Im new on this. On the console
Listening on your port
will logged only it does not continue and log
new client connected
This is my client side code:
<script>
var socket = io.connect('{{ env("APP_URL") }}:8890');
socket.on('notification-channel', function (data) {
var header_count_elem = $('#menubar #header-messages-count');
var count = header_count_elem.text();
if (data != 'no-sound') {
$.get('/notification/notif-alerts', function(response) {
header_count_elem.text((response.count == '0') ? '' : response.count);
if (data != 'no-sound') {
if (count != response.count) {
var sound = '<audio id="audioplayer" autoplay=true volume=1>' +
'<source src="{{ url('assets/themes/cpanel/alarms/notification_sound.mp3') }}" type="audio/mpeg">' +
'<source src="{{ url('assets/themes/cpanel/alarms/notification_sound.ogg')}}" type="audio/ogg">' +
'</audio>';
$('body').append(sound);
}
}
});
}
});

How to get response from socket.on before calling socket.emit

I am using node.js for creating an application that is maintaing the repository for the courses and its respective lectures and slides. And the retreival of courses of student (from mysql Db) is based on student name, the retreival of lectures is based on course name and soo on. The student name is stored on server and i must get it before calling server for getting course list.
Here is my code with more explanation:
var StdName;
$(document).ready(function () {
//connect to server
connectBind();
var socket = $("#click").data();
/**********Query database For student name!!!**********/
try {
socket.emit('askStdName');
}
catch (err) {
alert(err.message);
}
/********Query database For Courses!!!************/
try {
socket.emit('view-contents', StdName);
}
catch (err) {
alert(err.message);
}
});
//connecting to server
function connectBind() {
// connect to server on this port.
var socket = io.connect('http://localhost:3000');
$("#click").data(socket);
/**********GETTING NAME OF STUDENT*********/ //I WANT TO GET STUDENT NAME BEFORE THE QUERY FOR COURSES GET CALLED
try {
socket.on('get-Studentname', function (data) {
StdName = data;
alert("StdName: " + StdName);
});
}
catch (err) {
alert(err.Message);
}
And here is the server side script:
var express = require('express'); //load express
var http = require('http'); // then http
var socketIO = require('socket.io'); // then socket
var mysql = require('mysql');
var nodemailer = require("nodemailer");
var client = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'smartboard_db'
});
client.connect();
var app = express(); // create application
var server = http.createServer(app); //create server
var io = socketIO.listen(server); // start listening to server.
io.set('log level', 2);
// setup routing for static files.
app.use(express.static(__dirname + '/public'));
//start server
server.listen(3000, function(){
console.log('Server running...');
});
// First page
app.get('/', function(request, response) {
response.sendfile(__dirname + '/student-home.html');
});
io.set('log level', 1);
io.sockets.on('connection', function (socket) {
var sucess;
console.log("client connected");
/************SENDING THE NAME TO CLIENT*************/
socket.on('askStdName', function () {
console.log('sending student name to client');
socket.emit('get-Studentname', stdName);
});
/***********CHANNEL FOR GETTING COURSE LIST************/
socket.on('view-contents', function (stdName) {
//console.log("this is what I get from client for courses: " + stdName);
var DATABASE = 'smartboard_db';
client.query('USE ' + DATABASE);
/*****QUEURY FOR COURSES *****************/
client.query('SELECT courses FROM student_info WHERE name = "' + stdName + '"', function (err, results) {
if (err) {
throw err;
}
else {
console.log(JSON.stringify({ courses: results }));
socket.emit('courses', JSON.stringify({ courses: results }));
}
});
});
});
Can ny one help please?
If the get-Studentname event should always be followed by getting the courses:
// request student name
socket.emit('askStdName');
// wait for the student name to be returned, followed by requesting the courses
socket.on('get-Studentname', function (StdName) {
socket.emit('view-contents', StdName);
});
Alternatively, you can pass a function with the request for the student name, which the server can call to send back the response (instead of having the server emit a response). This does require a different setup on your server though:
// client code
socket.emit('askStdName', function(StdName) {
socket.emit('view-contents', StdName);
});
// server code should look like this:
socket.on('askStdName', function(done) {
// get student name (depends on your setup)
...
// call the function to return the value
done(StdName);
});

Nodejs socket.io is emitting message to client as number of clients connected

I made a nodejs server wich uses socket.io to establish communication with web client, the server is sending sockets to specific client, the issue is if I have 5 clients connected to the server, the client will receive the sent message 5 times!
here is my code :
var fs = require('fs'),
http = require('http'),
io = require('socket.io'),
qs = require('querystring');
sys = require ('util'),
url = require('url');
var message, AndroidID;
//Traitement Serveur nodejs
var server = http.createServer(function(req, res) {
if(req.method=='POST') {
var body = '';
req.on('data', function (data) {
body += data;
});
req.on('end',function(){
server.emit('sendingData', body);
console.log("Body : " + body);
});
res.write("success");
res.end();
} else {
res.writeHead(200, { 'Content-type': 'text/html'});
res.end(fs.readFileSync(__dirname + '/index.html'));
}
}).listen(8080, function() {
console.log('Listening at: http://localhost:8080');
});
var socket = io.listen(server);
var clients = {};
var compteur = 0;
// Traitement socket.io
socket.on('connection', function (client) {
clients[compteur] = client;
client.emit('firstConnection', client.id, compteur);
console.log('clients : ', clients);
compteur += 1;
client.on('message', function (msg) {
console.log('Message Received: ', msg);
client.broadcast.emit('message', msg);
});
server.on('sendingData', function(data){
message = data.substring(8, data.lastIndexOf('&'));
androidID = data.substr(-1);
console.log('[+] Sending Data : ', message ,' TO : ', parseInt(androidID));
clients[parseInt(androidID)].emit('androidmsg', message);
});
});
The nodejs server is receiving data from a php HTTPClient
You should put server.on('sendingData', function(data){...}); outside socket.on('connection', function (client){...});. This is because the sendingData event is for http server and not socket.io server.
Putting it inside socket.io connection handler makes it repeatedly execute for each connected client to socket.io server

Resources