socket.io private updates in specific rooms - socket.io

This question has been asked several times, but any of the answers is a solution to my problem.
issue:
There will be multiple accounts, and accounds will have multible users. In one specific account, the users will do some realtime updates - but the other accounts will be not affected from those real time changes, every accounts will be private.
We are planing to create room names for each account from cookie
Also we are using node in PHP project.
Sorry for my broken English!
// client side code
$( "#messageForm" ).submit( function() {
var nameVal = $( "#nameInput" ).val();
var msg = $("#messageInput").val();
socket.emit( 'message', { name: nameVal, message: msg } );
// Ajax call for saving datas
$.ajax({
url: "./ajax/insertMessage.php",
type: "POST",
data: { name: nameVal, message: msg },
success: function(data) {
}
});
return false;
});
socket.on( 'message', function( data ) {
var actualContent = $( "#messages" ).html();
var newMsgContent = '<li> <strong>' + data.name + '</strong> : ' + data.message + '</li>';
var content = newMsgContent + actualContent;
$( "#messages" ).append( newMsgContent );
});
//server side codes
var socket = require( 'socket.io' );
var express = require( 'express' );
var http = require( 'http' );
var app = express();
var server = http.createServer( app );
var io = socket.listen( server );
io.sockets.on( 'connection', function( client ) {
console.log( "New client !" );
client.on( 'message', function( data ) {
console.log( 'Message received ' + data.name + ":" + data.message );
//client.broadcast.emit( 'message', { name: data.name, message: data.message } );
io.sockets.emit( 'message', { name: data.name, message: data.message } );
});
});
server.listen( 8080 );

You can create private chat rooms as below.
Server side code
// usernames which are currently connected to the chat
var usernames = {};
// rooms which are currently available in chat
var rooms = ['room1','room2','room3'];
io.sockets.on('connection', function (socket) {
// when the client emits 'adduser', this listens and executes
socket.on('adduser', function(username){
// store the username in the socket session for this client
socket.username = username;
// store the room name in the socket session for this client
socket.room = 'room1';
// add the client's username to the global list
usernames[username] = username;
// send client to room 1
socket.join('room1');
// echo to client they've connected
socket.emit('updatechat', 'SERVER', 'you have connected to room1');
// echo to room 1 that a person has connected to their room
socket.broadcast.to('room1').emit('updatechat', 'SERVER', username + ' has connected to this room');
socket.emit('updaterooms', rooms, 'room1');
});
// when the client emits 'sendchat', this listens and executes
socket.on('sendchat', function (data) {
// we tell the client to execute 'updatechat' with 2 parameters
io.sockets.in(socket.room).emit('updatechat', socket.username, data);
});
socket.on('switchRoom', function(newroom){
// leave the current room (stored in session)
socket.leave(socket.room);
// join new room, received as function parameter
socket.join(newroom);
socket.emit('updatechat', 'SERVER', 'you have connected to '+ newroom);
// sent message to OLD room
socket.broadcast.to(socket.room).emit('updatechat', 'SERVER', socket.username+' has left this room');
// update socket session room title
socket.room = newroom;
socket.broadcast.to(newroom).emit('updatechat', 'SERVER', socket.username+' has joined this room');
socket.emit('updaterooms', rooms, newroom);
});
// when the user disconnects.. perform this
socket.on('disconnect', function(){
// remove the username from global usernames list
delete usernames[socket.username];
// update list of users in chat, client-side
io.sockets.emit('updateusers', usernames);
// echo globally that this client has left
socket.broadcast.emit('updatechat', 'SERVER', socket.username + ' has disconnected');
socket.leave(socket.room);
});
});
Client side code
var socket = io.connect('http://localhost:8080');
// 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', prompt("What's your name?"));
});
// listener, whenever the server emits 'updatechat', this updates the chat body
socket.on('updatechat', function (username, data) {
$('#conversation').append('<b>'+username + ':</b> ' + data + '<br>');
});
// listener, whenever the server emits 'updaterooms', this updates the room the client is in
socket.on('updaterooms', function(rooms, current_room) {
$('#rooms').empty();
$.each(rooms, function(key, value) {
if(value == current_room){
$('#rooms').append('<div>' + value + '</div>');
}
else {
$('#rooms').append('<div>' + value + '</div>');
}
});
});
function switchRoom(room){
socket.emit('switchRoom', room);
}
// on load of page
$(function(){
// when the client clicks SEND
$('#datasend').click( function() {
var message = $('#data').val();
$('#data').val('');
// tell server to execute 'sendchat' and send along one parameter
socket.emit('sendchat', message);
});
// when the client hits ENTER on their keyboard
$('#data').keypress(function(e) {
if(e.which == 13) {
$(this).blur();
$('#datasend').focus().click();
}
});
});
</script>
<div style="float:left;width:100px;border-right:1px solid black;height:300px;padding:10px;overflow:scroll-y;">
<b>ROOMS</b>
<div id="rooms"></div>
</div>
<div style="float:left;width:300px;height:250px;overflow:scroll-y;padding:10px;">
<div id="conversation"></div>
<input id="data" style="width:200px;" />
<input type="button" id="datasend" value="send" />
</div>
Reference Link:
http://psitsmike.com/2011/10/node-js-and-socket-io-multiroom-chat-tutorial/

Related

Notify specific user

I'm trying to make a notification system, but I don't know why the code not working... The redis shoots the event, and the event is received... On the "node server.js in CMD" returns:
C:\xampp\htdocs\test>node socket.js
Listening on Port 3000
{"message":"teste","user":1} //returns when publish redis in controller.
Controller:
public function fire(){
$redis = LRedis::connection();
$data = ['message' => 'teste', 'user' => 1];
if($redis->publish('message', json_encode($data))){
return response()->json(['sucesss' => 1]);
} else {
return response()->json(['error' => 0]);
}
}
Template.blade.php:
<script>
var socket = io('http://localhost:3000');
//console.log(socket); IS CONNECTED...
socket.on('message', function (data) {
console.log(data);
});
</script>
socket.js
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var Redis = require('ioredis');
var redis = new Redis();
redis.subscribe('message', function(err, count) {
});
redis.on('message', function(channel, message) {
console.log(message);
message = JSON.parse(message);
io.emit(channel + ':' + message.event, message.data);
});
http.listen(3000, function(){
console.log('Listening on Port 3000');
});
Console.log
Returns nothing...
If you help me to make work, how I can notify specific user? Example, user 1 creat a link, a link is commented by user 2, the user 1 be notified...

Socket IO v1.4.5 disconnect issue

I'm working on socket room and i try to disconnect from client side when i refresh the page, the problem is in console i receive message that socket id is disconnected, and another socket id generated but the old socket still active
here is my code in client side :
var roomSocket = io.connect("http://mysitehere.com:5001", {'forceNew': true});
var room = port;
roomSocket.on('connect', function () {
roomSocket.emit('starting', room);
console.log('emit connection to room');
});
roomSocket.on('connected', function () {
console.log('connected user');
});
roomSocket.on('message', function (data) {
console.log('Incoming message:' + data);
});
$(document).unload(function () {
roomSocket.disconnect();
});
my code in server js
socket.on('disconnect', function (data) {
console.log('------------------------------------');
console.log("DISCONNECTION : " + socket.id);
console.log('------------------------------------');
});
and the result :

socket io unique channel - emit without specifying the room

On my project each user is joining his unique channel (I know that the user is also in a socked id channel).
Client
var socket = io('http://localhost:8000/');
var room = "unique_id";
socket.on('connect', function () {
socket.emit('room', room);
});
socket.on("unique_id", function() {
console.log("test");
})
On the server side I am checking the rooms a user is connected to:
var io = require('socket.io')(8000);
io.on('connection', function(socket) {
var room;
socket.on('room', function(unique_id) {
socket.join(unique_id);
room = unique_id;
console.log(io.sockets.adapter.rooms); //show the unique_id room
io.to(room).emit('hello', 'msg');
});
socket.on(room, function(data) {
console.log(room);
})
});
Output on connect
{ 'DQOt2DX2IsHh-m9nAAAC': { sockets: { 'DQOt2DX2IsHh-m9nAAAC': true }, length: 1 },
'unique_id': { sockets: { 'DQOt2DX2IsHh-m9nAAAC': true }, length: 1 } }
Now I am using elephant.io to emit to the client as follows
$client = new Client(new Version1X('http://localhost:8000'));
$client->initialize();
$client->emit('unique_id', ['news' => 'bar']);
$client->close();
I think there is something wrong on my server side but I am not able to solve it. I need to process the events for the unique_id but how?
server side
var io = require('socket.io')(8000);
io.on('connection', function(socket) {
var room;
socket.on('room', function(address) {
socket.join(address);
room = address;
console.log(io.sockets.adapter.rooms);
io.to(room).emit('hello', 'msg');
});
socket.on('message', function(data) {
console.log(data.unique_id);
io.to(data.unique_id).emit('hello', 'msg');
})
});
elephant.io
$client->emit('message', ['unique_id' => 'foo']);
This is my solution which is working for me.

handle browser refresh socket.io

I have a requirement using node js that handles disconnecting a user from a chat application.
I am not sure how to handle telling the difference between a browser closing and a user refreshing the browser.
client.on('disconnect', function () {
console.log( 'Disconnected' );
// run mysql code to remove user from logged in table
});
I have googled for a couple hours and cannot find a solution.
This seems like something pretty simple and I think it is the keywords that I am using.
Can someone point me in the right direction on how to handle this?
Thanks in advance.
One way would be to generate a random UID and save it to local storage. Right after the client connects, send this UID to the server and check to see if that UID exists as a connected user. On the server side, set a timeout in the disconnect that gives the user 15 seconds or so before their unique UID is deleted from the "users online" data.
Client:
// When the client starts, create the uid.
localstorage.setItem('uUID', Math.random().toString(24) + new Date());
// Emit the UID right after connection
socket.emit('userLogin', localstorage.getItem('uUID');
Server:
var currentUIDS = [];
var userIsConnected = true;
io.sockets.on('connection', function (socket) {
var currentUID = null;
socket.on('userLogin', function (data) {
if (data !== null) {
if (currentUIDS.includes(data)) {
userIsConnected = true;
currentUID = data;
}
}
});
socket.on('disconnect', function () {
userIsConnected = false;
setTimeout(function () {
if (!userIsConnected) currentUIDS.pop(currentUID);
}, 15000);
});
});
I have a better solution for that to handle multiple users:
var users = [],
users_connected = [];
io.on('connection', function(socket) {
var uid = null;
// register the new user
socket.on('register', function (user_uid) {
if ( users_connected.indexOf(user_uid) < 0 ) {
users_connected.push(user_uid);
}
if ( users.indexOf(user_uid) < 0 ) {
console.log('New user connected: ' + user_uid);
users.push(user_uid);
// notify other clients that a new user has joined
socket.broadcast.emit('user:join', {
name: user_uid,
users: users_connected.length
});
}
uid = user_uid;
});
// clean up when a user leaves, and broadcast it to other users
socket.on('disconnect', function () {
users_connected.splice( users_connected.indexOf(uid), 1);
setTimeout(function () {
if ( users_connected.indexOf(uid) < 0 ) {
socket.broadcast.emit('user:left', {
name: uid
});
var index = users.indexOf(uid);
users.splice(index, 1);
}
}, 3000);
});
});

Load chat messages upon page load using websockets on node.js

Hi I'm developing a chat application using nodejs I'm new to node so I'm not very well familiar on its capabilities... I have made my application store its chat messages on mysql database only but I need to also display the past message and current one of a user here is the index.js
var mysql = require('mysql');
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var validator;
var connection = mysql.createConnection({ // setup the connection
host : "localhost",
user : "root",
password: "",
})
function getStdout(command, args, fn) {
var childProcess = require('child_process').spawn(command, args);
var output = '';
childProcess.stdout.setEncoding('utf8');
childProcess.stdout.on('data', function(data) {
output += data;
});
childProcess.on('close', function() {
fn(output);
});
}
app.use('/assets', require('express').static(__dirname + '/assets'));
app.use('/temp', require('express').static(__dirname + '/temp'));
app.get('/', function(req, res){
//res.sendfile(__dirname + '/' +validator);
res.send(validator);
});
//you should have only one io.on('connection')
io.on('connection', function(socket){
socket.on('chat message', function(msg){
console.log('message: ' + msg);
var myMsg= msg; // obtain the incoming msg
var strQuery = "INSERT INTO chat_storage(chat) VALUES(?)"; // your SQL string
connection.query("use schat"); // select the db
connection.query( strQuery, myMsg, function(err, rows){
if(err) {
// handle errors
} else {
io.emit('chat message', msg);
// message received
}
});
});
});
getStdout('php', ['message.php'], function(output) {
validator = output;
//start your server after you get an output
http.listen(3000, function(){
console.log(validator);
});
});
now here is the page for loading the chat messages
<?php startblock('script') ?>
<script src="/socket.io/socket.io.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script>
$(document).ready(function(){
$.ajax({
url: "localhost:3000/includes/message/store_chat.php",
type: "POST",
dataType: "html",
success: function (result) {
$("#messages").html(result);
}
});
});
var socket = io();
$('form').submit(function(){
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});
socket.on('chat message', function(msg){
$('#messages').append($('<li>').text(msg));
});
</script>
<?php endblock(); ?>
My idea was to the chat messages once the page loads I was trying to achieve it using ajax as you can see on the script that I have provided.. but it was no good didnt work at all Please help me
Couple of suggestions:
1) Store all of your messages in-memory ( unless you see this growing to several MB of data ) so that you can catch up any new client quickly.
2) Use socket.io to send the chat messages that have been stored rather than an AJAX call.
I've also included SequelizeJS instead of raw MySQL - It has a much cleaner raw query model and allows you to transition into a DAO model of sorts if you want to.
app.js
// Highly suggest replacing raw mysql with SequelizeJS - http://sequelizejs.com/
var Sequelize = require('sequelize'),
app = require('express')(),
http = require('http').Server(app),
io = require('socket.io')(http);
var validator;
var messages = [];
var sequelize = new Sequelize('schat', 'root', '');
app.use('/assets', require('express').static(__dirname + '/assets'));
app.use('/temp', require('express').static(__dirname + '/temp'));
app.get('/', function(req, res){
res.send(validator);
});
io.on('connection', function(socket){
// Send all previously sent messages
for( i in messages ) {
socket.emit('chat message', messages[i]);
}
socket.on('chat message', function(msg){
console.log('message: ' + msg);
// Push the message into the in-memory array.
messages.push(msg);
// Storage the message for when the application is restarted.
sequelize.query('INSERT INTO chat_storage(chat) VALUES("'+msg'")').success(function() {
// Insert was successful.
}).error(function (err) {
// Error inserting message
});
// Send the message to everyone
socket.broadcast.emit('chat message', msg);
});
});
function getStdout(command, args, fn) {
var childProcess = require('child_process').spawn(command, args);
var output = '';
childProcess.stdout.setEncoding('utf8');
childProcess.stdout.on('data', function(data) {
output += data;
});
childProcess.on('close', function() {
fn(output);
});
}
// Load Messages
sequelize.query('SELECT chat FROM chat_storage').success(function (rows) {
for( i in rows ) {
messages.push(rows[i].chat);
}
getStdout('php', ['message.php'], function(output) {
validator = output;
http.listen(3000, function(){
// Start server.
});
});
}).error(function (err) {
// Error!
});
php include
<?php startblock('script') ?>
<script src="/socket.io/socket.io.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script>
var socket = io();
$('form').submit(function(){
socket.emit('chat message', $('#m').val());
$('#messages').append($('li').text($('#m').val()));
$('#m').val('');
return false;
});
socket.on('chat message', function(msg){
$('#messages').append($('<li>').text(msg));
});
</script>
<?php endblock(); ?>

Resources