Dynamic Namespaces Socket.IO

后端 未结 5 586
再見小時候
再見小時候 2021-01-30 09:32

How can I use dynamic namespaces in socket.io.

I\'m looking in the (poor) documentation, and it says that namespaces must be used like this:

io.of(\'/news\

相关标签:
5条回答
  • 2021-01-30 09:40

    Here is one way. Here is a socket.io subclass I created to solve the problem:

    https://github.com/PencilCode/dynamic.io

    That subclass adds dynamic namespaces as well as virtual hostname support (each host can go into its own namespace tree if you like). That repo has some examples.

    Here is a universal socket.io listener that listens to every namespace requested, and logs a message for every socket that connects. You could listen to a different regexp to listen to any subset of namespaces.

    It works with the standard socket.io client library without any modification.

    var DynamicServer = require('dynamic.io');
    io = DynamicServer({
        host: true,                     // Enable virtual host handling
        publicStatus: true              // Enable /socket.io/status page.
    });
    // Any number of namespace patterns can be set up.
    // This is an example of a single catch-all pattern.
    io.setupNamespace(/.*/, function(nsp) {
        nsp.on('connect', function(socket) {
            console.log('a socket connected on', nsp.fullname());
        });
        nsp.expire(function() {
            console.log(nsp.fullname(), 'is expiring');
        });
    });
    io.listen(8888);
    
    0 讨论(0)
  • 2021-01-30 09:43

    As of version 2.1.1 I was able to make it work with this:

    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
    });
    
    0 讨论(0)
  • 2021-01-30 09:55

    I would use "rooms" to support your dynamic content.

    Server Side

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

    Client Side

    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);
    ....
    
    0 讨论(0)
  • 2021-01-30 10:02

    Server

    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>
    

    More details on: https://ingcamilorodriguez.wordpress.com/2016/06/21/como-hacer-namespaces-dinamicos-en-socket-io/

    0 讨论(0)
  • 2021-01-30 10:03

    Socket.IO supports 'rooms' (https://github.com/LearnBoost/socket.io/wiki/Rooms), you can use it instead of namespaces. Also when you need dynamic in routes (and you using express in your app) - best way is to use use route-engine from express box.

    • Best way to do dynamic routing with Express.js (node.js)
    • Using routes in Express-js
    • http://expressjs.com/api.html#app.routes
    • http://shtylman.com/post/expressjs-re-routing/
    • http://jordanhoff.com/post/22602013678/dynamic-express-routing

    However, if you still think that you need dynamic in namespaces in socket.io, here is small example how it can be implemented:

    User-side:

    var connect = function (ns) {
        return io.connect(ns, {
           query: 'ns='+ns,
           resource: "socket.io"
        });
    }
    
    var socket = connect('/user/12');
    

    Server-side:

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

    I hope this will help you!

    0 讨论(0)
提交回复
热议问题