2015-07-09 4 views
12

में हैं, क्या नामांकन के सभी उपयोगकर्ताओं को socket.io प्रसारण करना संभव है, जो कमरे ए और रूम बी दोनों में हैं लेकिन जो कमरे में नहीं हैं या कमरा बी?socket.io केवल उन उपयोगकर्ताओं को प्रसारित करता है जो कमरे ए और बी

यदि नहीं, तो मैं इसे स्वयं लागू करने के बारे में कैसे जाऊं? क्या किसी दिए गए कमरे में नामस्थान में सभी उपयोगकर्ताओं को पुनर्प्राप्त करने का कोई तरीका है?

मैं नोड में socket.io 1.0 के साथ काम कर रहा हूँ

संपादित करें: अगर कोई देशी विधि है, मैं कैसे जाना के बारे में इस तरह के रूप में अपने स्वयं के वाक्य रचना बनाने के लिए होगा: socket.broadcast.in('room1').in('room2').emit(...)?

+0

इस देखें: http://stackoverflow.com/a/24145381/3842050 यह मदद कर सकता है । – Blubberguy22

+0

आप दोनों को भेजकर क्लाइंट-साइड कर सकते हैं और केवल उसी ग्राहक पर दूसरे आगमन पर प्रतिक्रिया दे सकते हैं ... – dandavis

उत्तर

5

आप का उपयोग कर एक कमरे के सभी उपयोगकर्ताओं के देख सकते हैं (सन्दर्भ How to update socket object for all clients in room? (socket.io))

var clients = io.sockets.adapter.room["Room Name"] 

तो अपने 2 कमरों में 'रोस्टर सूची के लिए दो सरणियों को देखते हुए, आप इस सवाल का जवाब यहाँ की तरह कुछ का उपयोग कर चौराहे गणना कर सकता है (रेफरी: Simplest code for array intersection in javascript)

और अंत में आप दोनों कमरों में उपयोगकर्ताओं की उस सूची लेने के लिए और (संदर्भ का उपयोग कर की घटनाओं का उत्सर्जन कर सकते हैं: How to update socket object for all clients in room? (socket.io))

//this is the socket of each client in the room. 
var clientSocket = io.sockets.connected[clientId]; 

//you can do whatever you need with this 
clientSocket.emit('new event', "Updates"); 

वैकल्पिक रूप से छिपे कमरे हैं, जहां आप सभी कमरों का संयोजन बनाए रखते हैं, और दृश्यों के पीछे उन कमरों में उपयोगकर्ताओं को जोड़ते हैं, और फिर आप बस उन छिपे हुए कमरों में निकल सकते हैं। लेकिन यह घातीय वृद्धि समस्या से पीड़ित है।

+0

धन्यवाद! यह बहुत मूल्यवान जानकारी है। क्या आप जानते हैं कि मैं सॉकेट.ओ प्रोटोटाइप में इस प्रकार के व्यवहार को कैसे कार्यान्वित कर सकता हूं? यह कुछ ऐसा है जो मैं अपने पूरे कोड का उपयोग करने जा रहा हूं, इसलिए यह वास्तव में केवल चीजें होगी यदि मैं बस कॉल कर सकता हूं, कहूं, 'socket.broadcast.toAll ([...])। Emit (...)' और 'toAll()' फ़ंक्शन सभी कमरों के संघ को पकड़ लेता है और केवल उन लोगों को छोड़ देता है। –

0
io.sockets.adapter.room["Room A"].forEach(function(user_a){ 
    io.sockets.adapter.room["Room B"].forEach(function(user_b){ 
    if(user_a.id == user_b.id){ 
     user_a.emit('your event', { your: 'data' }); 
    } 
    }); 
}); 
1

ऐसा करने के लिए कोई अंतर्निहित तरीका नहीं है।

https://github.com/Automattic/socket.io/blob/master/lib/namespace.js 206 ... 221-224 ... 230

this.adapter.broadcast(packet, { 
    rooms: this.rooms, 
    flags: this.flags 
}); 

अब हम जानते हैं कि हर प्रसारण अस्थायी वस्तुओं, indexOf लुकअप, तर्क स्लाइस की एक गुच्छा बनाता है: तो सबसे पहले आइए देखें कि प्रसारण काम करता है ऊपर देखो ... और फिर एडाप्टर की प्रसारण विधि को कॉल करता है। देता है कि एक पर एक नज़र डालें:

https://github.com/Automattic/socket.io-adapter/blob/master/index.js 111-151

अब हम कमरे या सभी ग्राहकों के सभी ग्राहकों के माध्यम से भी अधिक अस्थायी वस्तुओं और पाश बना रहे हैं तो कोई जगह नहीं चुना गया था। लूप एन्कोड कॉलबैक में होता है। यही कारण है कि विधि यहां पाया जा सकता:

https://github.com/socketio/socket.io-parser/blob/master/index.js

लेकिन अगर हम अलग से कमरे के माध्यम से पाशन और ग्राहकों है कि कमरे में एक और कक्ष बी में दोनों मौजूद हैं पाने के बाद broadcast के माध्यम से लेकिन प्रत्येक ग्राहक के लिए हमारे पैकेट नहीं भेज रहे हैं क्या?

socket.emit यहाँ परिभाषित किया गया है: https://github.com/Automattic/socket.io/blob/master/lib/socket.js

client.js की packet विधि करने के लिए हमें लाता है कौन सा: https://github.com/Automattic/socket.io/blob/master/lib/client.js

प्रत्येक सीधे उत्सर्जित पैकेट अलग से इनकोडिंग किया जाएगा, जो फिर से, महंगा है। क्योंकि हम सभी उपयोगकर्ताओं को सटीक एक ही पैकेट भेज रहे हैं।

या तो, socket.io एडाप्टर वर्ग बदल सकते हैं और संशोधित प्रसारण विधि प्रोटोटाइप करने के लिए अपनी खुद की विधियों को जोड़ने या अनुकूलक वर्ग से इनहेरिट द्वारा अपने स्वयं के एडाप्टर रोल):

आपके प्रश्न का उत्तर करने के लिए। (var io = require('socket.io')(server, { adapter: yourCustomAdapter });)

या join और leavesocket.js के तरीकों को ओवरराइट करें। जो सुविधाजनक है कि उन तरीकों को अक्सर नहीं कहा जाता है और आपको एकाधिक फ़ाइलों के माध्यम से संपादन की परेशानी नहीं होती है।

Socket.prototype.join = (function() { 
    // the original join method 
    var oldJoin = Socket.prototype.join; 

    return function(room, fn) { 

     // join the room as usual 
     oldJoin.call(this, room, fn); 

     // if we join A and are alreadymember of B, we can join C 
     if(room === "A" && ~this.rooms.indexOf("B")) { 
      this.join("C"); 
     } else if(room === "B" && ~this.rooms.indexOf("A")) { 
      this.join("C"); 
     } 
    }; 
})(); 

Socket.prototype.leave = (function() { 
    // the original leave method 
    var oldLeave = Socket.prototype.leave; 

    return function(room, fn) { 

     // leave the room as usual 
     oldLeave.call(this, room, fn); 

     if(room === "A" || room === "B") { 
      this.leave("C"); 
     } 
    }; 
})(); 

और फिर C को प्रसारित करता है, तो आप A और B में सभी उपयोगकर्ताओं के लिए प्रसारित करना चाहते हैं। यह सिर्फ एक उदाहरण कोड है, आप कमरे के नामों को कड़ी मेहनत से नहीं बल्कि संभावित कक्ष संयोजनों पर लूप के बजाय सरणी या ऑब्जेक्ट का उपयोग करके इसे और बेहतर बना सकते हैं।

कस्टम एडाप्टर के रूप में socket.broadcast.in("A").in("B").emit() काम करने के लिए:

var Adapter = require('socket.io-adapter'); 

module.exports = CustomAdapter; 

function CustomAdapter(nsp) { 
    Adapter.call(this, nsp); 
}; 

CustomAdapter.prototype = Object.create(Adapter.prototype); 
CustomAdapter.prototype.constructor = CustomAdapter; 

CustomAdapter.prototype.broadcast = function(packet, opts){ 
    var rooms = opts.rooms || []; 
    var except = opts.except || []; 
    var flags = opts.flags || {}; 
    var packetOpts = { 
    preEncoded: true, 
    volatile: flags.volatile, 
    compress: flags.compress 
    }; 
    var ids = {}; 
    var self = this; 
    var socket; 

    packet.nsp = this.nsp.name; 
    this.encoder.encode(packet, function(encodedPackets) { 
    if (rooms.length) { 
     for (var i = 0; i < rooms.length; i++) { 
     var room = self.rooms[rooms[i]]; 
     if (!room) continue; 
     for (var id in room) { 
      if (room.hasOwnProperty(id)) { 
      if (~except.indexOf(id)) continue; 
      socket = self.nsp.connected[id]; 
      if (socket) { 
       ids[id] = ids[id] || 0; 
       if(++ids[id] === rooms.length){ 
       socket.packet(encodedPackets, packetOpts); 
       } 
      } 
      } 
     } 
     } 
    } else { 
     for (var id in self.sids) { 
     if (self.sids.hasOwnProperty(id)) { 
      if (~except.indexOf(id)) continue; 
      socket = self.nsp.connected[id]; 
      if (socket) socket.packet(encodedPackets, packetOpts); 
     } 
     } 
    } 
    }); 
}; 

और अपने अनुप्रयोग फ़ाइल में:

var io = require('socket.io')(server, { 
    adapter: require('./CustomAdapter') 
}); 
+0

यह अब तक का सबसे आशाजनक दृष्टिकोण है। मेरे पास परीक्षण करने का समय था, लेकिन इससे पहले कि आप अपने काम और प्रयास के लिए समाप्त हो जाएंगे, मैं आपको बक्षीस दूंगा। –

+0

धन्यवाद! :) ऐसे कई दृष्टिकोण भी हैं जिन्हें आप आजमा सकते हैं। जैसे 'ए' में सभी उपयोगकर्ताओं पर पुनरावृत्ति करते हुए, यह देखकर कि वे 'बी' में हैं (इंडेक्सऑफ का उपयोग करके उनकी 'रूम' प्रॉपर्टी पर) और फिर अपने संदेश को पहले एन्कोड करना और' सॉकेट के बजाय' socket.packet' के माध्यम से भेजना। emit'। मैंने कोड को आजमाया नहीं है, तो मुझे बताएं कि कुछ उम्मीद के अनुसार काम नहीं करता है। –

+0

करेंगे! मेरे पास इस सप्ताह के अंत में कुछ खाली समय होगा। मेरी मुख्य समस्या socket.io के प्रोटोटाइप में मेरे कार्यों को जोड़ रही थी –

संबंधित मुद्दे