Comment puis-je utiliser des espaces de noms dynamiques dans socket.io.
Je regarde dans la (pauvre) documentation , et il est dit que les espaces de noms doivent être utilisés comme ceci:
io.of('/news')
io.of('/akfda')
Pour utiliser un espace de noms, procédez comme suit: io.of("/namespace")
.
Dois-je enregistrer chaque espace de noms sur le serveur? Peut-être que je veux un espace de noms pour le contenu dynamique.
Comment puis-je faire quelque chose comme:
io.of('/:somethign/:id')
Socket.IO supporte les 'salles' ( https://github.com/LearnBoost/socket.io/wiki/Rooms ), vous pouvez l’utiliser à la place des espaces de noms. De même, lorsque vous avez besoin de dynamisme dans les itinéraires (et que vous utilisez Express dans votre application), le meilleur moyen consiste à utiliser route-engine depuis express box.
Cependant, si vous pensez toujours que vous avez besoin de dynamique dans les espaces de noms dans socket.io, voici un petit exemple de la manière dont cela peut être implémenté:
Côté utilisateur:
var connect = function (ns) {
return io.connect(ns, {
query: 'ns='+ns,
resource: "socket.io"
});
}
var socket = connect('/user/12');
Du côté serveur:
var url = require('url');
, ev = new events.EventEmitter()
// <ns name>: <ns regexp>
var routes = {
// /user/:id
'user': '^\\/user\\/(\\d+)$',
// /:something/:id
'default': '^\\/(\\\w+)\\/(\\d+)$'
};
// global entry point for new connections
io.sockets.on('connection', function (socket) {
// extract namespace from connected url query param 'ns'
var ns = url.parse(socket.handshake.url, true).query.ns;
console.log('connected ns: '+ns)
//
for (var k in routes) {
var routeName = k;
var routeRegexp = new RegExp(routes[k]);
// if connected ns matched with route regexp
if (ns.match(routeRegexp)) {
console.log('matched: '+routeName)
// create new namespace (or use previously created)
io.of(ns).on('connection', function (socket) {
// fire event when socket connecting
ev.emit('socket.connection route.'+routeName, socket);
// @todo: add more if needed
// on('message') -> ev.emit(...)
});
break;
}
}
// when nothing matched
// ...
});
// event when socket connected in 'user' namespace
ev.on('socket.connection route.user', function () {
console.log('route[user] connecting..');
});
// event when socket connected in 'default' namespace
ev.on('socket.connection route.default', function () {
console.log('route[default] connecting..');
});
J'espère que cela t'aidera!
Je voudrais utiliser "salles" pour soutenir votre contenu dynamique.
Du côté serveur
var server = require('http').createServer(),
io = require('socket.io')(server);
io.on('connection', function(socket){
var room = socket.handshake['query']['r_var'];
socket.join(room);
console.log('user joined room #'+room);
socket.on('disconnect', function() {
socket.leave(room)
console.log('user disconnected');
});
socket.on('chat message', function(msg){
io.to(room).emit('chat message', msg);
});
});
server.listen(3000);
Côté client
var socket_connect = function (room) {
return io('localhost:3000', {
query: 'r_var='+room
});
}
var random_room = Math.floor((Math.random() * 2) + 1);
var socket = socket_connect(random_room);
socket.emit('chat message', 'hello room #'+random_room);
....
Voici un moyen. Voici une sous-classe socket.io que j'ai créée pour résoudre le problème:
https://github.com/PencilCode/dynamic.io
Cette sous-classe ajoute des espaces de noms dynamiques ainsi que la prise en charge du nom d’hôte virtuel (chaque hôte peut accéder à sa propre arborescence d’espaces de noms si vous le souhaitez). Ce repo a quelques exemples.
Voici un écouteur universel socket.io qui écoute tous les espaces de noms demandés et enregistre un message pour chaque socket qui se connecte. Vous pouvez écouter une expression rationnelle différente pour écouter n’importe quel sous-ensemble d’espaces de nom.
Il fonctionne avec la bibliothèque client standard socket.io sans aucune modification.
var DynamicServer = require ('dynamic.io'); io = DynamicServer ({ Host: true, // Activer la gestion des hôtes virtuels publicStatus: true // Activer la page /socket.io/status. }); // Vous pouvez configurer un nombre illimité de modèles d’espace de nom. // Voici un exemple modèle catch-all. io.setupNamespace (/.*/, fonction (nsp) { nsp.on ('connect', fonction (socket) { console.log ('une socket connectée sur', nsp.fullname ()); }); nsp.expire (function () { console.log (nsp.fullname () , 'expire'); }); }); io.listen (8888);
Depuis la version 2.1.1
, je pouvais le faire fonctionner avec ceci:
wss.of((nsp, query, next) => {
const { token } = query;
// Do your authentication or whatever here...
// If success
next(null, true);
}).on('connect', (socket) => {
// socket connected to your namespace
});
Serveur
var MAX_CLIENTS = 5;
var namespace_queue = [];
function searchObjectOnArray(nameKey, myArray) {
for (var i = 0; i < myArray.length; i++) {
if (myArray[i].id === nameKey) {
return myArray[i];
}
}
}
function createNamespace(data){
var ns = {
//id: require('node-uuid')(),
id : data.name,
clients: 0,
};
namespace_queue.Push(ns);
return ns;
}
createNamespace({name: 'primer'});
io.of('').on('connection', function(socket){
console.log('-' + socket.id);
/// Welcome to the new client
socket.emit('Welcome', {SocketId : socket.id});
socket.on('JoinToApp', function (data, callback) {
var namespaceToConnect = searchObjectOnArray(data.namespace, namespace_queue)
if(namespaceToConnect.clients <= MAX_CLIENTS){
var dynamicNamespace = io.of('/' + namespaceToConnect.id);
dynamicNamespace.on('connection', function(ns_socket){
console.log('user connected to ' + namespaceToConnect.id);
dynamicNamespace.emit('hi', 'everyone!');
});
namespaceToConnect.clients++;
}
callback({namespaces:namespace_queue});
})
socket.on('createNamespace',function(data,join_cb){
createNamespace(data);
join_cb({message:'Namespace created'});
});
});
Client
<input id="namespaceInput" type="text" placeholder="New namespace name">
<input id="namespaceToConnect" type="text" placeholder="namespace to connect">
<button onclick="javascript: createNamespace()">Create Namespace</button>
<button onclick="javascript: joinToNamespace()">Connect to Namespace</button>
<script src="https://cdn.socket.io/socket.io-1.4.5.js"></script>
<script>
var socket = null;
(function(){
socket = io.connect('http://localhost:3000/');
})()
function createNamespace(){
var namespaceName = document.getElementById("namespaceInput").value;
socket.emit('createNamespace', {name : namespaceName}, function(data){
alert(data.message);
})
}
function joinToNamespace(){
var name = document.getElementById("namespaceToConnect").value;
socket.emit('JoinToApp', {namespace: name}, function(data){
console.log('Namespaces created:');
console.log(data)
var ns_socket = io.connect('http://localhost:3000/' + name);
ns_socket.on('connect',function(){
console.log('joined namespace ' + name);
});
ns_socket.on('hi', function(data){
console.log('hi ' + data)
})
});
}
</script>
Plus de détails sur: https://ingcamilorodriguez.wordpress.com/2016/06/21/como-hacer-namespaces-dinamicos-en-socket-io/