I'm having problems when I try to join a socket to a room. The name of the room is the socket.id and it is assigned when it is connected. But when this happens it doesn't join to room. What could be the error?
Client code:
var socket = io();
socket.on("connect", function() {
socket.emit("joinRoom", socket.id);
});
socket.on("agentMessage", function(msg) {
$('#messages').append("<div class='agent-messages'><p>" + msg + "</p></div>");
});
Server code:
io.on("connection", (socket) => {
let roomID;
socket.on("joinRoom", (socket_id) => {
roomID = socket_id;
socket.join(roomID);
socket.to(roomID).emit("agentMessage", "Welcome!");
});
socket.on("disconnect", () => {
socket.leave(socket_id);
});
});
Your client is actually joining the room, but it is not sending the message. As you are sending message from the server side you cannot send it using the socket, as socket represents a client connection and cannot throw events on behalf of server. You have to use
io.to(roomID).emit("agentMessage", "Welcome!");
as io represents a server instance and can throw events on behalf of server(actually it is the server).
Reference
Related
Scenario is i have a server where socket(1) runs i have one more server where socket(2) client connects to socket(1)
I have one browser socket which connects to socket(1)
Idea is to do request from browser and bring data from socket(2) server
Not sure how to difference between socket clients as all the sockets are similar to socket(1)
Ideally there will be multiple browser sockets and multiple socket(2) clients
Browser sockets can make request to any of the socket(2) clients
How to implement it using nodejs socket.io
Server
socket.on('action', (action) => {
if(action.type === 'server/hello'){
io.sockets.emit('broadcast',{ description: clients + ' clients connected!'});
console.log('Got hello data!', action.data);
}
});
Browser client
var socket = io.connect('localhost:3000', {reconnect: true});
socket.on('connect', function(data) {
socket.emit('joined', 'Hello World from client this is client plxx');
});
socket.on('response2', function(data) {
console.log("got it ", data);
$('#messages').append($('<li>').text(JSON.stringify(data)));
});
Server client
var io = require('socket.io-client');
var socket = io.connect('http://localhost:3000', {reconnect: true});
socket.on('broadcast', function (t) {
socket.emit("data", {data: 32})
console.log('broadcast! my host is est');
});
i should be able to communicate between socket clients
What I understood from your question is: you need to differentiate between sockets from different clients.
To solve that I would suggest simply emitting the socket source from the client on connect.
And on the server split the sockets into two lists.
Example:
Server
const BROWSER_CLIENTS = {};
const SERVER_CLIENTS = {};
io.on("connection", socket => {
socket.on("source", payload => {
if (payload == "browser")
BROWSER_CLIENTS[socket.id] = socket;
else if (payload == "server")
SERVER_CLIENTS[socket.id] = socket;
});
socket.on("disconnect", () => {
delete BROWSER_CLIENTS[socket.id];
delete SERVER_CLIENTS[socket.id];
});
});
Browser Client
socket.on("connect", () => {
socket.emit("source", "browser");
});
Server Client
socket.on("connect", () => {
socket.emit("source", "server");
});
Now when you receive an event you can detect from which source it originated. And if you need to send to all sockets of one type of clients you can simply do this:
Server
for (let i in BROWSER_CLIENTS)
BROWSER_CLIENTS[i].emit("Hello Browsers")
for (let i in SERVER_CLIENTS)
SERVER_CLIENTS[i].emit("Hello Servers")
EDIT: I found this link and thought you could make use of it. Socket.io Rooms
The nodejs (10.16) and express (4.16) backend server (server) runs with socket.io 2.2.0 for a chat app. The message received on the server will be broadcast to the clients connecting to the same room (channel). The socket.io instance is created in index.js:
const io = require('socket.io')(server);
io.on('connection', async (socket) => {
socket.my_id = "";
console.log("socket.id : ", socket.id);
app.set("socket", socket);
console.log("Socketio server is initialized");
//disconnect
socket.on('disconnect', async function() {
//if (socket.my_id) helper.RemoveSocketUser(user.fort_token, socket.my_id);
console.log('disconnected event');
});
});
server.listen(port, () => {};
Then after a message is saved on the server, the socket is used to broadcast to the clients in the same room.
try {
await msg.save();
msg.user_name = req.user.name;
msg.user_avatar = req.user.user_data.avatar;
const io = req.app.get("io");
const socket = req.app.get('socket');
const room = msg.event_id.toString();
socket.my_id = req.user.id;
socket.join(room);
console.log("socket in new message : ", socket.id);
console.log("msg before broadcast : ", msg.data.msg_body);
io.to(room).emit("event message", msg);
return res.status(200).send(req.body.data.msg_body);
} catch (err) {
console.log("Error in saving/braodcasting a new message", err);
return res.status(400).send(err.message);
};
From the console output, the socket.id is the same for 2 clients connecting to the same room and chatting. Here is a output for Android emulator running on port 8081:
socket in new message : b0po9l6hGZUi9xVDAAAE
msg before broadcast : 8081
Here is another android emulator running on port 9090:
socket in new message : b0po9l6hGZUi9xVDAAAE
msg before broadcast : 9090
However the socket.id on clients side is not the same. What causes the server using the same socket.id for 2 clients?
What you are trying to do is accessing socket object stored in express,
which will update socket object every time new socket get connected that's why you are getting same socket id [ last connected ].
to access specific socket from outside the io connection scope, you have to get the socket instance from io object.
you need to store socket id somewhere in database or memory like redis.
const socketid = `get user's latest connected socket id.`
cont socket = io.sockets.sockets[socketid];
socket.emit('req', { data: "something"})
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 want my client-side code to send the server the user's userid when establishing the connection, then i want the server to check the database for new messages for each user that is connecting, and send the user the number of new messages it has when new messages are available.
My client-side code:
var socket = io.connect('http://localhost:8000');
socket.on('connect', function () {
socket.emit('userid', '1');
});
socket.on('new_message', function (data) {
var number_of_messages= "<p>"+data.number+"</p>";
$('#container').html(number_of_messages);
});
My server-side code:
io.sockets.on( 'userid', function (data) {
console.log('userid: '+data);
});
My problem is that the above code is not working: the userid is never received by the serverside and the on('userid') is never called.
My question is how to know which socket sent this user id and how to send to only this specific socket a certain message.
I have solved the problem by saving the clients socket and their id into a global array. this is not a good solution but it works; I know there are rooms and namespaces but I never used it..
socket.io namespaces and rooms
however,
(I used express)
client:
var socket = io.connect('http://localhost:3000',{reconnection:false});
socket.once('connect', function() {
socket.emit('join', '#{id}');
};
server:
var clients = [];
app.io.on('connection', function(socket) {
socket.on('join', function(data) {
clients.push({
ws: socket,
id: data
});
//retrive the messages from db and loop the clients array
//and socket.send(things)
}
}
I am using socket.io 1.4.0.
I am trying to send a message to put the client in a room called 'myroom', then send a message to the room from the client and then get the response from the room. However I get no response from using
socket.to('myroom').emit('message', 'what is going on, party people?');
Here is my client code:
socket.on('connect', function() {
// Connected, join the booking room for to receive messages for this room
socket.emit('room', 'myroom');
});
socket.on('message', function(msg){
console.log('message: ' + msg);
});
socket.emit('booking room message', {roomid: 'myroom', message: 'hello'});
Here is my server code:
// Set up the Socket.IO server
var io = require("socket.io")(server)
.use(function(socket, next) {
// Wrap the express middleware
sessionMiddleware(socket.request, {}, next);
})
.on("connection", function(socket) {
console.log(socket.request.session);
if (socket.request.session.passport) {
var userId = socket.request.session.passport.user;
//Sign up client for the room from client side.
socket.on('room', function(room) {
socket.join(room);
console.log(userId + ' has joined booking room: ' + room);
});
//make a room for this user
socket.join(userId);
console.log("User ID: " + userId + " connected. socketID: " + socket.id);
socket.on('disconnect', function() {
console.log("User ID: " + userId + " disconnected.");
});
socket.on('booking room message', function(data) {
console.log('message sent from browser to a room');
console.log(data);
socket.to('myroom').emit('message', 'what is going on, party people?');
});
}
});
I get a message back from the server as expected when I use :
socket.emit('message', 'what is going on, party people?');
So there is something wierd going on with the join room function. A couple of things to note, I have some middleware tha gets the ID from express - dont think that is having any impact. Also I create a seperate room for the userID.
Can a user be in two rooms at once? I am not sure what is causing this.
Thanks,
it seemed that neither to or in will send the response back to the same client. The code above did send to other clients in the room however.