Nodejs join users to custom rooms - javascript

You suppose i have 3 room such as room1, room2 and room3
i want to join some users to this rooms, how can i do that?
my code doesn't correct and i can't do that
var socket = require('socket.io'),
express = require('express'),
fs = require('fs'),
app = express(),
server = require('http').createServer(app),
io = socket.listen(server),
port = process.env.PORT || 3000,
redis = require("redis"),
redisClient = redis.createClient(),
forever = require('forever'),
log = require('log4node');
var io_redis = require('socket.io-redis');
io.adapter(io_redis({host: 'localhost', port: 6379}));
require('sticky-socket-cluster/replace-console')();
var options = {
workers : require('os').cpus().length,
first_port : 8000,
proxy_port : 3000,
session_hash: function (req, res) {
return req.connection.remoteAddress;
},
no_sockets: false
};
var room = ["room1","room2","room3"];
require('sticky-socket-cluster')(options, start);
function start(port) {
io.sockets.on('connection', function (socket) {
socket.on('room1', function (room) {
socket.join(room[0])
});
socket.on('room2', function (room) {
socket.join(room[1])
});
});
server.listen(port, function () {
console.log('Express and socket.io listening on port ' + port);
});
}
when i use this code to join users as :
socket.on('room1', function (room) {
socket.join(room[0])
});
i get no result and code doesn't work and i don't know how can i do that

Related

How can I show my connected clients to the new client in socket.io?

I am currently doing socket.io project. When I connect to new socket it shows my input username on the "usersDiv" where all clients should be there. But the thing is when I open another tab and input my name, it only has the name of the new client but when I switch to the other tab 2 client names are there. the new client doesn't show recent connected client input.
Here is my Code:
app.js(server)
const app = express();
const socket = require('socket.io');
const server = app.listen(8001, function(){
console.log('listening to port 8001')
});
const io = socket(server);
app.use(express.static('./views'));
app.set('views','./views');
app.set('view engine','ejs');
app.get('/', function(req, res){
res.render('index');
});
io.on('connection', function(socket){
console.log('Made Connection');
socket.on('username', function(data){
let users = [];
users.push(data.userName);
io.emit('joined', users)
});
});
client.js(client)
let username = prompt('What is your username?');
let usersDiv = document.getElementById('users');
let container = document.getElementById('container');
let socket = io();
let clear = document.getElementById('clear');
let circle = document.createElement('div');
socket.emit('username', {
userName: username
})
socket.on('joined', function(data){
usersDiv.innerHTML += data + '<br>';
})
As Chris G pointed out you need to declare let users = []; outside of the event handler connection.
For an example in app.js using sockets with a express server:
const express = require('express');
const app = require('express')();
const server = require('http').createServer(app);
const io = require('socket.io')(server);
app.use(express.static("public"));
app.set('view engine','ejs');
app.get('/', function(req, res){
res.render('index');
});
let users = [];
io.on('connection', function(socket) {
console.log('Made Connection');
socket.on('username', function(data) {
io.emit('joined', users);
users.push(data.userName);
});
});
const listener = server.listen(process.env.PORT, () => {
console.log('app is running on port ' + listener.address().port);
});
Then for client side you can create path like: public/client.js
let username = prompt('What is your username?');
let usersDiv = document.getElementById('users');
let container = document.getElementById('container');
let clear = document.getElementById('clear');
let circle = document.createElement('div');
let socket = io.connect();
socket.emit('username', {
userName: username
});
socket.on('joined', function(data) {
usersDiv.innerHTML = data.join('<br>');
});
Also you need to be careful using html when you are appending the username or messages someone could do a xss attack.

Triggering socket.io real-time notifications from Express 4 middleware

I am building a real-time notification system using socket.io. This is my server-side code at the moment:
bin/www:
var app = require('../app');
var server = http.createServer(app);
var io = app.io
io.attach(server);
server.listen(port, function(err) {
if (err) console.log(err);
console.log('Listening on port ' + port + '...');
});
app.js:
var socket_io = require('socket.io');
var express = require('express');
var app = express();
var io = socket_io();
app.io = io;
require('./config/socket')(app.io);
config/socket.js:
var User = require('../controllers/user');
module.exports = function (io) {
io.on('connection', function (socket) {
console.log('Socket.io connected');
socket.emit('connection', "Connection created.");
socket.on('send notification', function(data) {
User.createNotification(socket.request.user, data);
});
});
};
routes/index.js:
var express = require('express');
var User = require('../controllers/user');
var router = express.Router();
router.post('/order', User.order);
module.exports = router;
controllers/user.js:
var User = require('../models/user').model;
var io = require('socket.io');
module.exports = {
order: function(req, res) {
/* some create order code */
io.emit('send notification', 'Your order was successful!');
res.sendStatus(200);
}
}
I keep getting the error TypeError: io.emit is not a function whenever I try to call the route POST /send even though I am clearly initiating socket.io in my app.js and bin/www files and requiring it in controllers/user.js. All the examples I've seen online emit notifications from within this part:
io.on('connection', function (socket) {
socket.emit(event, msg);
});
but I want my notifications to be triggered from the middleware so I can send custom notifications to the user when certain events happen in the application backend.
Try the following instead:
io.on('connection', function(socket){
socket.on('xxx', function(obj){
io.emit('xxx', {xxx: xxx})
})
})
This should suppress your TypeError:.

Nodejs implementing socket cluster dont work my sockets

I'm trying to implementing cluster on nodejs and using Socket.io in my application, after some search and introduced about that and finding sticky-socket-cluster i try to use that, here is sample code which i use the documentetion of library, but login socket not working and dont print log
require('sticky-socket-cluster/replace-console')();
var options = {
workers : require('os').cpus().length, // total workers (default: cpu cores count).
first_port : 8000, // 8000, 8001 are worker's ports (default: 8000).
proxy_port : 3000, // default (5000).
session_hash: function (req, res) {
return req.connection.remoteAddress;
},
no_sockets: false // allow socket.io proxy (default: false).
};
require('sticky-socket-cluster')(options, start);
function start(port) {
var express = require('express');
var http = require('http');
var app = express();
var server = http.Server(app);
var socket = require('socket.io')(server);
socket.on('connection', function (socket) {
console.log("socket.io connection handler...");
});
socket.on('login', function (data) {
console.log(data.username);
});
server.listen(port, function () {
console.log('Express and socket.io listening on port ' + port);
});
}

Socket.io socket emit not being called

I have this index.js file on the client:
var socket;
var init = function() {
// Setup Socket:
socket = io.connect();
// Setup Event Handlers:
setEventHandlers();
// Connect to Server:
socket.emit('connect', {
name : "User Name"
});
console.log("Client Init Complete.");
}
var setEventHandlers = function() {
// Set Routes For Connections
socket.on("connection resp", onConnected);
}
var onConnected = function(data) {
console.log(data.resp);
}
And I have this code on the server:
// SETUP:
var express = require('express');
var app = express();
var http = require('http').Server(app);
var request = require('request');
var path = require('path');
var socket = require('socket.io')(http);
var server_port = process.env.OPENSHIFT_NODEJS_PORT || 8080;
var server_ip_address = process.env.OPENSHIFT_NODEJS_IP || '0.0.0.0';
var bodyParser = require('body-parser')
var fs = require('fs');
// SETUP:
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended : false
}));
app.configure(function() {
app.use(express.static(path.join(__dirname, 'public')));
})
var setEventHandlers = function() {
socket.sockets.on("connection", onInit);
};
var onInit = function(client) {
client.on("connect", onConnect);
};
var onConnect = function(data) {
console.log("Called");
}
// Send index page html
app.get('/', function(req, res) {
res.sendfile("public/html/index.html");
});
// Turn on server
http.listen(server_port, server_ip_address, function() {
console.log("App Listening on " + server_ip_address + ", server_port "
+ server_port);
});
setEventHandlers();
The issue is that on the onConnect on the server is never called. Eventhough I call socket.emit("connect") on the client.
After further testing, it seems that the socket id is undefined: this.id returns undefined.
You need to add quotes to the parameters in the socket.emit function like this:
// Connect to Server:
socket.emit('connect', {
'name' : 'User Name'
});
You should initialize your socket variable through io.connect("server address") and has i see in your code you have not passed any parameter to io.connect
.If server is in your local machine then connect to it by io.connect("http://localhost").
For more information see Docs. socket.io-client

Socket.io - listen events in separate files in node.js

For example my idea is:
File1.js
io.sockets.on('connection', function (socket) {
socket.on('file1Event', function () {
//logic
});
});
File2.js
io.sockets.on('connection', function (socket) {
socket.on('file2Event', function () {
//logic
});
});
This code is for a node server, will I have problems with this code?
Nope, just use the same "io" object.
File1.js
exports = module.exports = function(io){
io.sockets.on('connection', function (socket) {
socket.on('file1Event', function () {
console.log('file1Event triggered');
});
});
}
File2.js
exports = module.exports = function(io){
io.sockets.on('connection', function (socket) {
socket.on('file2Event', function () {
console.log('file2Event triggered');
});
});
}
app.js
var app = require('http').createServer(handler)
, io = require('socket.io').listen(app)
, fs = require('fs')
, file1 = require('./File1')(io)
, file2 = require('./File2')(io)
app.listen(3000);
function handler (req, res) {
fs.readFile(__dirname + '/index.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
index.html
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost');
socket.emit('file1Event'); // 'file1Event triggered' will be shown
socket.emit('file2Event'); // 'file2Event triggered' will be shown
</script>
Be careful not to generate a new connection event for each file. You should use the same on('connection') event, otherwise after 10 files imported, you will get this error from node: MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 connection listeners added. Use emitter.setMaxListeners() to increase limit.
The better way is to do like this in your main file:
io.on('connection', function (socket) {
require('pathToSocketRoutesFile1')(socket);
require('pathToSocketRoutesFile2')(socket);
require('pathToSocketRoutesFileN')(socket);
return io;
};
and in each separate file:
module.exports = function(socket) {
socket.on('eventName1', function() {
//...
});
socket.on('eventName2', function() {
//...
});
};
Another option is to create a rootSocket which handles the initial connection and then passes the socket to other handlers.
const rootSocket = (io) => {
io.sockets.on('connection', (socket) => {
authorization(socket);
chat(socket);
});
};
exports.default = rootSocket;
You Can use IO module in any route just create global middleware.
socketiomw.js
module.exports = (io)=>{
return (req,res,next)=>{
req.io = io;
next();
}
}
middlewares.js
module.exports.global = {
socketIo:require('./socketiomw'),
// add other global middleware
};
index.js
const express = require('express');
const app = express();
const port = 3000;
const http = require('http');
const server = http.createServer(app);
const { Server } = require("socket.io");
const io = new Server(server);
//global middleware initialization
app.use(require('./middlewares').global.socketIo(io));
app.get('/notify',(req,res)=>{
req.io.emit("hello");
req.io.to("someRoom").emit("some event");
req.io.to("room1").to("room2").to("room3").emit("some event");
req.io.of("/").adapter.on("create-room", (room) => {
console.log(`room ${room} was created`);
});
req.io.of("/").adapter.on("join-room", (room, id) => {
console.log(`socket ${id} has joined room ${room}`);
});
req.json({ success:true })
);
server.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
I used this in global middleware so i can use this io module in any routes
rootSocket.js :
const rootSocket = (io) => {
io.on('connection', (socket) => {
console.log('New connection');
// possibility to outsource events
socket.on('myEvent', () => {
console.log('myEvent triggered');
});
});
}
module.exports = rootSocket;
index.js :
const express = require('express');
const app = express();
//app.use(express.json());
//const cors = require('cors');
//app.use(cors());
const http = require('http');
const server = http.createServer(app);
const socketIo = require('socket.io');
const io = socketIo(server);
const rootSocket = require('./rootSocket')(io);
const port = 8000;
// process.env.PORT for production
server.listen(port, () => console.log('server started on ' + port));

Categories

Resources