Socket.io (1.0) + Multiple client connections - node.js

So I'm connecting two variable (objects) to the same socket.io server, one's job is to handle public feed and another's to handle private feed with extended functions.
I've attempted the "force new connection" option, however both connections seem to still use utilize the same socket + session Id.
I originally didn't include code because this is so basic, but here you go:
var socket = io(host);
socket.on('connect', function(e){
socket.emit('join', {
channel: stream_channel,
});
});
One is var socket, the other is var socket2. When it connects to the server it emits "join" where:
io.on('connection', function(socket){
socket.on('join', function(d){
socket.join(d.channel);
});
});

I was able to figure this out by:
Subscribing the websocket to multiple rooms
Appending additional variables at each POST to define the room to emit to
I was able to determine that:
Utilizing the same host will always keep the same session id / socket (even with force connection enabled)
Potentially using a different host or namespace would allow a separation in connection
It's better to keep a single connection with multiple rooms

Related

I can't get my head around websockets (via socket.io and node.js)

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);
});
})

Socket.io client specific variable

How do I store session specific info in Socket.io?
var client={}; //is this static across all sockets (or connected clients) that are connected?
io.on('connection', function(socket){
client.connectiontime=Date.now();
});
//on another io.on('connection') for the same connected client
io.on('connection', function(socket){
store(client.connectiontime);
}
How do I use the client variable only for the operations related to the currently connected client if it is considered static?
First, each socket is given a name that can be used to refer to it, but that changes each time the same client connects so this would not be useful if it is supposed to remain after the client leaves. If your goal is to store the connection time somewhere (a database?) then you would have to get a unique identifier from the client that could be used to find them again similar to a login. You would then pass the date object into the function that handles storing that time.
You should note though, that 'connection' is only called the first time the socket connects. A connection is not the event you normally would be using for when a client does something unless they disconnects between each access of the server program.
If you are sure you want to just use the Client object, you would likely have to create a client array and use the socket id as a key to access the object later. You would then have something like
array[socket.id].connectiontime = Date.now()
var client={}; //is this static across all sockets (or connected clients) that are connected?
var clients = [];
io.on('connection', function(socket){
clients[] = {
id : socket.id
connectiontime : Date.now()
}
});
//on another io.on('connection') for the same connected client
io.on('connection', function(socket){
// Here you would search for the object by socket.id and then store
store(client.connectiontime);
}

Design pattern for WebSockets through Socket.IO

I am building a complex chatting application, using WebSockets. I use Node.JS's Socket.IO library to implement the protocol. Should I create a separate namespace for each Chat, Or separate room for each Chat?
What is the main difference between Namespaces and Rooms in Socket.IO?
Typically rooms are used if all the clients are of the same type.
Use namespaces if there are different types of clients. For example, anonymous users and authenticated users. In this case one may need to process incoming connection requests differently.
var guest = io.of('/guest');
guest.on('connection', function(socket) {
console.log('A guest client connected');
});
var user = io.of('/user');
user.on('connection', function(socket) {
var authenticated = authenticate(); //authenticate the user
if (!authenticated) {
// log attempt and disconnect the client
}
});

socketIO handshake behavior when connecting to different namespaces

I am having troubles with socketIO (nodejs) and using multiple namespaces. Maybe I misunderstood how to use it, but this is how I understood it should work.
Server side (nodejs)
io.of('/game').on('connection', socket => {
console.log(socket.handshake.query);
console.log('user connected to game socket', socket.id);
})
io.of('/api').on('connection',socket => {
console.log(socket.handshake.query);
console.log('user connected to api socket', socket.id);
}
Client side (browser)
function test (){
gameSocketTest = io.connect('http://localhost:4003/game',{query:{test:'test'}});
apiSocketTest = io.connect('http://localhost:4003/api');
}
The weird thing is that the query (that I only send to the "game" namespace) arrives in both handlers, also the one of the api.
If I inverse the order of the client side code to:
function test (){
apiSocketTest = io.connect('http://localhost:4003/api');
gameSocketTest = io.connect('http://localhost:4003/game',{query:{test:'test'}});
}
the query in the handshake is empty in both handlers server side. So my conclusion is that one way or another the same handshake is used for both connections (however the socket ids are different for both).
Is it "uberhaupt" possible to do what I am trying to do? If so, what am I not understanding with this weird handshake behavior.
In my understanding calling on the client side "io.connect()" should create 2 separate socket io clients, each with their own handshake.
Thanks for any help!
Andries
You must open new connection explicitly as Socket.IO tries to be smart and re-use connections (which causes a lot of connection issues actually) The way around this is use the force new connection option in your io.connect
gameSocketTest = io.connect('http://localhost:4003/game',{query:{test:'test'}});
apiSocketTest = io.connect('http://localhost:4003/api', {'force new connection': true});
From docs
When called, it creates a new Manager for the given URL, and attempts
to reuse an existing Manager for subsequent calls, unless the
multiplex option is passed with false. Passing this option is the equivalent of passing 'force new connection': true

Nodejs and socket.io selecting sockets to broadcast

I have a nodejs + socket.io solution and sockets join different rooms. How can i select sockets from different rooms to broadcast to them a certain message without using a for loop that will stall the application for all users?
The solution is simple, make every "special" user (the ones that you want to group) connect to a secret channel with Socket.IO, in your server-side code:
var io = require('socket.io').listen(80);
io.sockets.on('connection', function (socket) {
if (condition_to_determine_is_user_has_access) {
socket.join('specials');
socket.broadcast.to('specials').emit("new special user has joined");
}
});
You may also want to block access to that channel to un-allowed users, based on cookies / sessions.
Read more here: http://www.danielbaulig.de/socket-ioexpress/

Resources