Is it possible to global emit only to sender but outside the socket.on('connect') event? I'm looking for something like socket.broadcast.to().emit() which I can use in app.post method, which is not in connect method, so I can't use just socket.emit
app.post('/room', function(req, res) {
io.sockets.emit('something');
});
'something' I want to emit only to SENDER
My code:
socket_id;
app.post('/room', function(req, res) {
if (req.body.user == ''){
io.sockets.socket(socket_id).emit('usernameError', 'Type your username');
}
else if (users[req.body.user] !== undefined ) {
io.sockets.socket(socket_id).emit('usernameError', 'Username exists.');
}
else{
users[req.body.user] = req.body.user;
user = req.body.user;
io.sockets.emit('newUser', user+' join to the room');
res.render('room');
}
});
io.sockets.on('connection', function(socket) {
socket.username = user;
socket.join('room1');
socket.id = socket_id;
});
As far as I understand you want to send "something" to the user that just came to /room page, right?
If so, you can't do it in app.post method because this code will execute before the client will receive the HTML code,
and thus handshake between client and server will not be established.
I think the best solution would be executing the following code on the client side on /room page only:
var socket = io.connect('/'); //your socket.io connection (may be different)
socket.on('something', function(data) {
console.log(data);
});
socket.emit('i_am_room_page'); //tell server we are on /room page
And on the server:
io.sockets.on('connection', function(socket) {
socket.on('i_am_room_page', function(data) {
socket.emit('something', {your: 'data'});
});
});
Hope this helps
If somehow you can store the socektID of the sender in a variable, then you can emit to that particular client in app.post method. Do something like this:
var id;
io.sockets.on('connection', function(socket){
socket.on('some event'){
id = socket.id;
}
});
and do this in app.post method:
app.post('/room', function(req, res) {
io.sockets.socket(socketid).emit('event name', {data: yourData});
});
Though I've proposed this solution but your approach doesn't seem too convincing.
Related
how to emit the event with using particular_room [io.to(socket.id).emit('sendData') ]at cross domain
I've tried this,
server side
io.emit('sendData', data);
clientside
var socket = io('https://localhost:3000/', { transports: ['websocket'] });
socket.on('sendData', function (data) {
console.log(data);
})
above syntax are perfectly working on cross domain
but I want to emit with particular room at cross domain
io.to(socket.id).emit('sendData', data)
io.broadcast.to(socketid).emit('message', 'for your eyes only'); //sending to individual socketid
Reference link -> Cross-domain connection in Socket.IO
Kindly help to solve this!
I Understood your code, you just emit the initial connection on the socket.io server
io.on("connection", function(socket){
socket.emit('sendsocketid', data);
})
Cross-domain clientside
var socket = io('https://localhost:3000/', { transports: ['websocket'] });
var obj= [];
socket.on('sendsocketid', function (data) {
console.log(data);
// Now You Can Customize the or add the client Socket .id
var NewSocketid = {
id: socket.id
}
Obj.push(data, NewSocketid)
socket.emit("emitnewSocketId", Obj)
})
socket.on("emitnewSocketId", function(data){
consoleo.log(Obj[1].NewSocketid)
//Now You can emit the new socket id
io.to(Obj[1].NewSocketid).emit('sendData', data)
})
I am on a websocket (socket.io) and I want to be able to force disconnect on a given user. I use this on my server file:
// kickout
socket.on('kickout', (sckid) => { //sckid is the socket.id of the kicked-out user
io.to(sckid).emit('kicked');
});
});
// kicked out
socket.on('kicked', () => {
socket.disconnect();
});
Then I do socket.emit('kickout', 'someusersocketid'); on my frontend but it won't work for some reasons. Seems like the server listens to "kickout" alright but so to "kicked". Why is that?
Try this one:
var clients = {}
sockets.on('connection', function(socket) {
clients[socket.id] = socket;
socket.on('disconnect', function() {
delete clients[socket.id];
});
});
I have a problem when I try send message from a client emisor with "emit" and I try catch the message with "on" in a client receptor.
I don't know what is the problem, my code is this:
Emisor Client:
socket.emit("callDriver", data);
Receptor Client:
socket.on("sendToDriver", function(data){
console.log(data);
})
Server:
var io = require('socket.io')(server);
io.on('connection', function(socket){
socket.on('callDriver', function(data){
console.log(data);
socket.emit('sendToDriver', data);
})
})
Thanks community
Guys I resolved the problem, it's strange in the official documentation of Socket.io they say that when you send data in a .emit you should send this with "socket.emit()" (server side) but I try change socket for io and with this mode work it.
In conclusion:
// I changed this:
io.on('connection', function(socket){
socket.on('callDriver', function(data){
console.log(data);
socket.emit('sendToDriver', data);
})
})
// for this:
io.on('connection', function(socket){
socket.on('callDriver', function(data){
console.log(data);
io.emit('sendToDriver', data);
})
})
Thanks guys!
Here is a simple rooms solution for you. The init() part is very low-tech/simple but you did not say how you intend to populate the socket server with the client userId/session-data when you connect to the server for the first time.
//Client
socket.on('connect',()=>{
socket.on('init',()=>{
socket.emit('init', 'userid')
})
})
socket.on("sendToDriver", function(message){
console.log(message);
})
sendMessage(message){
let data = {userId: "userId", message: message}
socket.emit("callDriver", data);
}
//Server
var io = require('socket.io')(server);
//Triggered by each client separately.
io.on('connection', function(socket){
socket.on('init', (driverId)=>{
//When your web socket starts for the first time, each user creates their own room with their main userId that is used in your mobile app.
//Your setup is so basic, that the server('connection') -> server.emit('init') -> client.on('init') -> client.emit('init') flow is the most sane example for now.
//However this init() setup is primitive -- you need an authentication flow and to pass up the userId/session data with a socket.io 'middleware' function or the 'socket.io-auth' library (recommended)
socket.join(driverId)
})
socket.emit('init')
//Data sent to callDriver will contain the userId of the desired receipient. Since this user is already waiting in that room for us, we join it,
//send the message, and then leave immediately.
socket.on('callDriver', function(data){
socket.join(data.driverIdToCall)
socket.to(data.driverIdToCall).emit('sendToDriver', data.message);
socket.leave(data.driverIdToCall)
})
})
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..
I wondered if someone could help figure out what I am doing wrong:
My client web page initiates a connection with my server, and listens to a long running process whose state is getting updated in the db by a worker process on another thread, emitting updates back to the browser. I define a socket.io connection in the app.post() method. This is handled by the poll() function below (scroll down a bit past the invite checking code)
However, when a new web client connects, it's messages get added to the previous client's as if there were just one channel. Why isn't there a separate unique channel for each browser?
//Create server
var express = require('express'),
app = express(),
http = require('http'),
server = http.createServer(app),
io = require('socket.io').listen(server);
io.set('log level', 1); // reduce logging
io.configure(function () {
io.set("transports", ["xhr-polling"]);
io.set("polling duration", 10);
});
app.post('/api/users', function (req, res) {
if (!req.body.auth.accessToken) {
req.body.auth.accessToken = req.body.auth.authResponse.accessToken;
} //fb return object is different depending on whether it is a first login or subsequent
logger.log('debug', '/api/users:POST', req.body);
io.sockets.on('connection', function (socket) {
socket = socket;
socket.emit('update', {
status: 200 //send initialization ping
});
//check if user has valid invite, if not try to invite
db.getTotalUserInvites(function (err_inv, res_total) {
db.getUserInvite(req.body.fid, function (err_check, res_check) {
logger.log('debug', 'Total invites issued=' + res_total);
//process report - all we need is accesToken, processReport will do the rest
mine_fb.processUser(req.body.auth.accessToken, socket, function (User,socket) { //pass channel properly
db.getReportStatus(User.fid,socket, function (result,socket) {
logger.log('debug', 'report status', result);
if (result) {
if (socket && (result.report_status == -1)) {
logger.log('debug', 'report already processed. retrieving uniq_id ' + result.uniq_id);
socket.emit('update', {
status: -1,
uniq_id: result.uniq_id
});
return true;
} else {
if (socket && (result.report_status >= 0)) {
logger.log('debug', 'we are in the middle of processing report ' + result.uniq_id);
//in this case we become a listener and not a speaker
function poll(socket) {
db.getReportStatus(User.fid, socket,function (r,socket) {
socket.emit('update', { //!!!! THIS EMITS TO ALL CONNECTED BROWSERS
status: r.report_status,
uniq_id: r.uniq_id
}); //...socket
if ((r.report_status >= 0) && (socket)) {
logger.log('debug', 'polling...');
_.delay(poll, 2000, socket);
}
}); //get rerpot
}; //end poll
socket.on('disconnect', function () {
socket=null;
});
poll(socket);
} // else we're in the middle
} //done checking status
} //end of seq
});
return res.send();
});
});
});
});
});
While it is not clear how to help you I can tell what's going on in your code:
app.post('/api/users', function (req, res) {
// some code
io.sockets.on('connection', function (socket) {
// some code
});
});
Whenever a user POSTs something to /api/users a new handler is attached to io.sockets (that's what .on does). But these handlers are never removed, so each time a new connection is established all attached handlers fire. That's where your broadcasting comes from.
You have to separate app.post(...) from io.sockets.on('connection',...) (they should be independent, both defined at module level, not nested). I'm sure it won't be easy (you will probably have to authenticate a user twice for example) but that's the only reasonable way.
You shouldn't put your io.sockets.on('connection', function (socket) inside the app.post scope.
Just put it outside and try again, it will probably work correctly.
Listening to connexion should be done once when the server starts, not each time a client hits some URL.