I have this scenario with socket.io:
A socket connects and joins a room and he is the master. Other sockets join his room. When master disconnects I want to kick all other sockets from this room.
I thought of this:
socket.on('disconnect', function(data){
// if socket's id == room he is the master and kick other sockets from this
// room and join them to a room of their own identified by their ids.
});
I want to do this without too much logic and for loops to stall the application. Is it possible to something like io.sockets.leave(socket.room)?
alessioalex's answer returns an error because it tries to call "leave" on an array of sockets. This is a working solution:
io.sockets.clients(socket.room).forEach(function(listener) {
listener.leave(socket.room);
});
I am not 100% sure, but after reading Socket.IO's documentation on github I think this should work:
io.sockets.in(socket.room).leave(socket.room);
Related
I'm using io.sockets.emit in the router like
db.SomeModel.find({},
function(err, modelDate) {
io.sockets.emit('eventName', modelData);
}
);
What would happen if a socket took like 10sec (just an example) to be established, and before it is established I try to emit something. Would it give some undefined error or..? I'm new to node and asynchronous programming in general. Thanks a lot.
What if socket establishing is not finished before it?
It will just be skipped and no data will be sent to a socket that is has not yet established its connection.
io.sockets.emit() loops through a list of connected sockets and sends to each one individually. If a socket is not done connecting, then it won't be in the list that socket.io is iterating through so no data will be sent to it.
I'm new to websockets/socket.io/node.js. I'm trying to write a card game app, but pretty much all the example tutorials I've found are creating chat applications. So I'm struggling to get my head around the concepts and how they can be applied to my card game.
Keeping it simple, the card game will involve two players. The game involves moving cards around the table. Each player has to see the other player's moves as they happen (hence the need for constant connections). But the opponents cards are concealed to the other.
So two people browse to the same table then click to sit (and play, when both seats are taken). Using
io.on("connection", function(sock){
//socket events in here
});
am I creating the one socket ('io', or 'sock'?) that both clients and the server share, or is that two separate sockets (server/clientA and sever/clientB)? I ask, because I'm struggling to understand what's happening when a message is emitted and/or broadcast. If a client emits a message, is that message sent to both the server and the other client, or just the server? And then, further does it also send the message to itself as well?? It seems as though that's the logic... or what is the purpose of the 'broadcast' method?
From a functional perspective, I need the server to send different messages to each player. So it's not like a chatroom where the server sends the chat to everyone. But if it's one socket that the three of us share (clients and server), how do I manage who sees what? I've read about namespaces, but I'm struggling to work out how that could be used. And if it's two separate sockets, then I can more easily imagine sending different data to the separate clients. But how is that implemented - is that two 'io' objects, or two 'sock' objects?
Finally, I've got no idea if this is the sort of long-winded question that is accepted here, so if it's not, can someone direct me to a forum that discussions can occur? Cheers!
(in case it matters I'm also using Expressjs as the server).
Edit to add:
Part of my confusion is regarding the difference between 'io' and 'sock'. This code eg from the socket.io page is a good example of methods being applied to either of them:
io.on('connection', function(socket){
socket.emit('request', /* */); // emit an event to the socket
io.emit('broadcast', /* */); // emit an event to all connected sockets
socket.on('reply', function(){ /* */ }); // listen to the event
});
WebSocket server side listens for incoming socket connections from clients.
Each client upon connection opens its own socket between him and server. The server is the one that keeps track of all clients.
So once client emits the message server is listening for, the server can do with that message whatever. The message itself can contain information about who is the recipient of that message.
The server can pass the message to everyone or broadcast it to specific user or users based on information your client has sent you or some other logic.
For a card game:
The server listens for incoming connections. Once two clients are connected both of them should emit game ID in which they want to participate. The server can join their sockets in one game(Room) and all of the communication between those two clients can continue in that room. Each time one of the clients passes data to the server, that data should contain info about the recipient.
Here is one simple example that could maybe get you going:
Client side
// set-up a connection between the client and the server
var socket = io.connect();
// get some game identifier
var game = "thebestgameever";
socket.on('connect', function() {
// Let server know which game you want to play
socket.emit('game', game);
});
function makeAMove(move)
{
socket.emit('madeAMove', {move:move, game:game});
}
socket.on('move', function(data) {
console.log('Player made a move', data);
});
Server side
io = socketio.listen(server);
//listen for new connections from clients
io.sockets.on('connection', function(socket) {
// if client joined game get his socket assigned to the game
socket.on('game', function(game) {
socket.join(game);
});
socket.on('madeAMove', function(data){
let game = data.game;
let move = data.move;
io.sockets.in(game).emit('move', move);
});
})
I want to create a channel in a websocket server using node js and to send message to the subscribers.
I need a simple code to start.
Thank you for your help.
Using socket.io, you can easily create channels to differentiate subscribers to different groups. Socket.io calls the channels Rooms and you can read the documentation for details.
In essence, when clients connect to the socket, you have them join a specific room:
io.on('connection', function(socket){
socket.join('some room');
});
Whenever you emit an event (sending messages in your case), you can send it to clients in that room:
io.to('some room').emit('some event');
I have socket id of each connected user stored in my database. When any user posts a comment or status, I want to broadcast the same to all his/her connections using socket id stored in my database.
I can emit the message to individual client using his/her socket id by using io.sockets.connected[ socket.id ].emit('privateMsg', 'Hello! How are you?');
But how do I emit the same to the array of socket id which i have generated using select query from my database.
You can use concept of rooms. Whenever a socket connection arrives, join the connections to a room. And on disconnect, remove the socket from the room.
socket.on('connection', function () {
socket.join('room1');
});
socket.on('disconnect', function () {
socket.leave('room1');
});
Now when you want send messages to sockets connected on a room, you can broadcast it to room.
socket.broadcast.to('room1').emit('eventName', data);
You could dynamically create a room for each socket that connects and emit to it without having to loop over the entire array every time. Like so:
socketids.foreach(function(socketid){io.sockets.connected[socketid].join(sendingSocket.id);});
Then you can emit to those sockets from your sending socket by doing the following:
sendingSocket.to(sendingSocket.id).emit('publicMessage', 'Hello! How are you?')
As a side-note, I don't think keeping socket ids that change in a database is the best approach, since they have no persistence at all. You may want to try to find a better identifier for your database.
For anyone who visites this thread. After Socket.io 3.x we can pass arrays of room names and socket ids to io object. like this:-
socketIds = [xlksdf09sdfsk,sdosdifns90sdf,..........]
io.sockets.to(socketIds).emit('hello','recieving all sockets')
roomNames = [roomA,roomB]
io.to(roomNames).emit('hello','recieves each member of the rooms')
// Event is also not emmitted multiple times on the client side
// evern if single socketId is present in multiple rooms.
I have an application that uses several namespaces to differentiate between different kind of clients, so since the beginning I separate them in this manner (I'm using cluster and spawn 4 processes)
//server code
io.of("/TYPE_ONE").on("connection", function(socket){
console.log("Client connected to TYPE_ONE with id:\t"+socket.id+"\t"+process.env.NODE_WORKER_ID);
});
io.of("/TYPE_TWO").on("connection", function(socket){
console.log("Client connected to TYPE_TWO with id:\t"+socket.id+"\t"+process.env.NODE_WORKER_ID);
});
//client code
//for type one
socket = io.connect("http://mydomain.com/TYPE_ONE", socketOptions);
//different files always, only one type sent to each client
//for type two
socket = io.connect("http://mydomain.com/TYPE_TWO", socketOptions);
All of a sudden, after looking at the console, when a single client connects and I get the following output:
Client connected to TYPE_ONE with id: 1234 3
.
.
.
Client connected to TYPE_TWO with it: 1234 3
(same id and workerId as previous connection)
I'm certain that there is only one connection being made to the server, t
I'm wondering what could be causing this? Because Ive looked through my code, and simplified the methods to the stubs I just showed, and can't seem to find the issue.
Thanks for your help.
There are no errors in your code: you have only one connection, therefore socket connects to namespaces with one socket.id. I don't know how to make many connections, maybe you should try two ports of connection, or connect/listen server multiple times.
To solve your problem i would use one connection, but think about how to sturcure your site. For example, use rooms and store in session NEW user id's to figure out in what room or namespace to put user.
"Multiple namespaces and multiple rooms can share the same (WebSocket) connection"
socket.io rooms or namespacing?
If you want to differentiate clients, you can put theme in another rooms in one namespace and having their socket.id check in what room they are (or join rooms with socket.id name (.joind(socket.id)).
https://github.com/LearnBoost/socket.io/wiki/Rooms
It turns out, at some point in my code, I had a io.of("/TYPE_ONE").socket(socket.id).emit(message); and that socket belonged to the namespace TYPE_TWO, so it seems whenever you send a message to a socket from a namespace to which he isn't connected, this will automatically connect it to that said namespace. Weird though.