2012-11-13 13 views
33

मैं node.js के साथ सॉकेट का उपयोग करने की कोशिश कर रहा हूं, मैंने सफलता प्राप्त की लेकिन मुझे नहीं पता कि मेरे कोड में ग्राहकों को कैसे अंतर किया जाए। सॉकेट के विषय में हिस्सा यह है:webSocketServer node.js क्लाइंट को अलग करने के लिए कैसे करें

var WebSocketServer = require('ws').Server, 
    wss = new WebSocketServer({port: 8080}); 
wss.on('connection', function(ws) { 
    ws.on('message', function(message) { 
     console.log('received: %s', message); 
     ws.send(message); 
    }); 
    ws.send('something'); 
}); 

इस कोड को अपने ग्राहक जे एस के साथ ठीक काम करता है।

लेकिन मैं किसी विशेष उपयोगकर्ता या मेरे सर्वर पर सॉकेट वाले सभी उपयोगकर्ताओं को एक संदेश भेजना चाहता हूं।

मेरे मामले में मैं एक ग्राहक के रूप में एक संदेश भेजता हूं और मुझे एक प्रतिक्रिया प्राप्त होती है लेकिन अन्य उपयोगकर्ता कुछ भी नहीं दिखाते हैं।

मुझे उदाहरण के लिए उपयोगकर्ता 1 वेबसाकेट के माध्यम से सर्वर को एक संदेश भेजता है और मैं उपयोगकर्ता 2 को एक सूचना भेजता हूं जिसकी सॉकेट खुली है।

+0

_you_ कैसे परिभाषित करते हैं जो कनेक्शन "user1" है और जो "user2" क्या है? – lanzz

+0

मुझे वास्तव में पता नहीं है, मैंने – Ajouve

+2

को कनेक्ट करते समय उपयोगकर्ता को सॉकेट सत्र देने का विचार किया, ठीक है, जैसे ही आप कनेक्शन के _user पहचान_ को जानते हैं (उदाहरण के लिए जब आपका उपयोगकर्ता अपना उपयोगकर्ता नाम संदेश के रूप में भेजता है), तो आप कर सकते हैं एक शब्दकोश में इसका नाम संदर्भित करें (उदाहरण के लिए 'कनेक्शन [उपयोगकर्ता नाम] = ws') और उसके बाद, कहीं और, आप' कनेक्शन [उपयोगकर्ता नाम] .send (संदेश) ' – lanzz

उत्तर

30

आप आसानी से उपयोगकर्ता आईडी को एक सरणी क्लाइंट [] में असाइन कर सकते हैं, इसमें सभी उपयोगकर्ता शामिल होंगे। आप सीधे नीचे दिए गए सभी उपयोगकर्ताओं को संदेश भेज सकते हैं:

var WebSocketServer = require('ws').Server, 
    wss = new WebSocketServer({port: 8080}), 
    CLIENTS=[]; 

wss.on('connection', function(ws) { 
    CLIENTS.push(ws); 
    ws.on('message', function(message) { 
     console.log('received: %s', message); 
     sendAll(message); 
    }); 
    ws.send("NEW USER JOINED"); 
}); 

function sendAll (message) { 
    for (var i=0; i<CLIENTS.length; i++) { 
     CLIENTS[i].send("Message: " + message); 
    } 
} 
+1

यदि आप ग्राहकों की अनूठी आईडी को आगे भेजते हैं, तो आप संदेश का स्रोत क्लाइंट भी प्राप्त कर सकते हैं। –

+15

इस समाधान को स्केल नहीं किया जा सकता है क्योंकि परिवर्तनीय क्लाइंट्स नोडजेएस की एक प्रक्रिया के भीतर रहता है। यहां तक ​​कि यदि हम कई प्रक्रियाओं को फोर्क करके एकाधिक कोर का उपयोग करते हैं, तो क्लाइंट्स एक साझा स्मृति आवंटन नहीं है, प्रत्येक प्रक्रिया क्लाइंट की अपनी सूची बनाए रखती है। इसलिए, इसे उसी प्रक्रिया से बात करने के लिए बाद के कनेक्शन की आवश्यकता होगी। –

+1

क्या आप क्लाइंट साइड भी पोस्ट कर सकते हैं? – johannesMatevosyan

6

This code snippet वर्लीज़ सर्वर में वास्तव में मुझे बहुत मदद मिली। भले ही आप ws का उपयोग कर रहे हों, कोड आसानी से अनुकूल होना चाहिए। मैं यहाँ महत्वपूर्ण भागों का चयन किया है: के रूप में जुड़ा हुआ कोड में दिखाया गया

// initialization 
var connections = {}; 
var connectionIDCounter = 0; 

// when handling a new connection 
connection.id = connectionIDCounter ++; 
connections[connection.id] = connection; 
// in your case you would rewrite these 2 lines as 
ws.id = connectionIDCounter ++; 
connections[ws.id] = ws; 

// when a connection is closed 
delete connections[connection.id]; 
// in your case you would rewrite this line as 
delete connections[ws.id]; 

अब आप आसानी से एक प्रसारण() और sendToConnectionId() फ़ंक्शन बना सकते हैं।

उम्मीद है कि मदद करता है।

+0

ए 'इन इन' लूप के लिए एक मानक के विपरीत, लूप को प्रसारित करने के लिए उपयोग करने की आवश्यकता होगी, क्योंकि (सहयोगी) सरणी में "छेद" हैं। – Tobiq

2

मैं ws ऑब्जेक्ट से fd का उपयोग कर रहा हूं। यह प्रति ग्राहक अद्वितीय होना चाहिए।

var clientID = ws._socket._handle.fd; 

जब मैं एक नया ब्राउज़र टैब खोलता हूं तो मुझे एक अलग संख्या मिलती है।

पहले ws 11 थी, अगले था 12.

+7

मुझे लगता है कि फ़ाइल डिस्क्रिप्टर, एफडी, फिर से उपयोग किया जा सकता है यदि कोई उपयोगकर्ता छोड़ देता है और कोई अन्य उपयोगकर्ता जुड़ता है ... अनिवार्य रूप से वे – user772401

+0

रीसाइक्लिंग कर सकते हैं यदि पत्तियों का उपयोग आप इसे अपने सत्र से हटा सकते हैं, और जब कोई भी उसी नंबर के साथ जुड़ता है आपकी सत्र तालिका – muni764

+0

में अप्रचलित कुंजी होगी शायद समस्या हो सकती है कि _handle को विघटित करने पर आप इसे तालिका से हटा नहीं सकते हैं, शायद आप ws के अंदर हैंडल को सहेज सकते हैं? – muni764

6

यह जो WebSocket प्रयोग कर रहे हैं निर्भर करता है। उदाहरण के लिए, सबसे तेजी से एक है, यहां पाया: तो फिर बाद में अपने कोड में आप सभी को भेजने के लिए wss.broadcast (संदेश) का उपयोग कर सकते

var WebSocketServer = require('ws').Server, 
    wss = new WebSocketServer({host:'xxxx',port:xxxx}), 
    users = []; 
wss.broadcast = function broadcast(data) { 
wss.clients.forEach(function each(client) { 
    client.send(data); 
}); 
}; 

: https://github.com/websockets/ws इस पद्धति के माध्यम से एक प्रसारण करने में सक्षम है। एक पीएम को एक व्यक्तिगत उपयोगकर्ता को भेजने के लिए मैं निम्नलिखित करता हूं:

(1) मेरे संदेश में मैं सर्वर को भेजता हूं, इसमें एक उपयोगकर्ता नाम (2) फिर, मैसेज में मैं वेबस्क्रिप्ट को सरणी में सहेजता हूं उपयोगकर्ता नाम, फिर बाद में उपयोगकर्ता नाम से इसे पुनः प्राप्त:

wss.on('connection', function(ws) { 

    ws.on('message', function(message) { 

     users[message.userName] = ws; 

(3) एक विशेष उपयोगकर्ता आप तो उन [उपयोगकर्ता नाम] .send (संदेश) कर सकते हैं करने के लिए भेजने के लिए;

+0

क्या आप कोड के लिए कोई लिंक प्रदान कर सकते हैं जहां आप उपयोगकर्ता नाम शामिल करते हैं? – johannesMatevosyan

+0

क्लाइंट पर, जब आप कोई संदेश भेजते हैं तो आप एक JSON ऑब्जेक्ट बना सकते हैं, फिर इसे इस तरह स्ट्रिंग करें: var sendObject = {userName: "Tim", pm: true, message: "आप कैसे हैं?"}; ws.send (JSON.stringify (SendObject)); इसके अलावा, एनारोस में आप हेडर में एक जेसन पेलोड भेज सकते हैं, जैसे: डब्ल्यूएस.ओपेन (यूरी, [JSON.stringify ({userName: "Tim"})]); फिर आप इसे ws.upgradeReq.headers का उपयोग कर सर्वर पर पार्स कर सकते हैं और स्ट्रिंग को JSON.parse के माध्यम से अपनी ऑब्जेक्ट में वापस कर सकते हैं। मैंने उपयोगकर्ता समूह बनाने के लिए इस विधि का उपयोग किया है, लेकिन इसका उपयोग उपयोगकर्ता सरणी को स्टोर करने के लिए भी किया जा सकता है। –

+0

मेरे पास एक समान समस्या है लेकिन इसे हल नहीं कर सका, क्या आप देख सकते हैं? http://stackoverflow.com/questions/35535700/websockets-send-messages-and-notifications-to-all-clients-except-sender – johannesMatevosyan

0

यदि आप खुले कनेक्शन का मतलब रखते हैं तो क्लाइंट द्वारा, तो आप पहचानकर्ता के रूप में ws.upgradeReq.headers['sec-websocket-key'] का उपयोग कर सकते हैं। और सभी सॉकेट ऑब्जेक्ट्स को सरणी में रखें।

लेकिन यदि आप अपने उपयोगकर्ता को पहचानना चाहते हैं तो आपको सॉकेट ऑब्जेक्ट में उपयोगकर्ता विशिष्ट डेटा जोड़ना होगा।

3

आप कनेक्शन ऑब्जेक्ट की जांच कर सकते हैं।इसमें प्रत्येक कनेक्टेड क्लाइंट के लिए अंतर्निहित पहचान है; आप इसे यहाँ पा सकते हैं:

let id=ws._ultron.id; 
console.log(id); 
+0

आप कैसे जानते हैं Ultron.id अद्वितीय है? मुझे इससे संबंधित कुछ भी नहीं मिला। – adelriosantiago

+0

विभिन्न कनेक्शनों का उपयोग करके इसे अपने आप पर आज़माएं। –

9

NodeJS में आप सीधे ws ग्राहक को संशोधित करने और कस्टम अलग से प्रत्येक ग्राहक के लिए जिम्मेदार बताते हैं जोड़ सकते हैं। इसके अलावा आपके पास वैश्विक चर wss.clients है और कहीं भी इसका उपयोग किया जा सकता है। अगले कोड कोशिश करते हैं और leat दो ग्राहकों पर कनेक्ट करने का प्रयास करें:

var WebSocketServer = require('ws').Server; 
var wss = new WebSocketServer({ 
    server: httpsServer 
}); 


wss.getUniqueID = function() { 
    function s4() { 
     return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1); 
    } 
    return s4() + s4() + '-' + s4(); 
}; 

wss.on('connection', function connection(ws, req) { 
    ws.id = wss.getUniqueID(); 

    wss.clients.forEach(function each(client) { 
     console.log('Client.ID: ' + client.id); 
    }); 
}); 

तुम भी ग्राहक कनेक्शन URL में सीधे पैरामीटर पास कर सकते हैं:

https://myhost:8080?myCustomParam=1111&myCustomID=2222

कनेक्शन समारोह आप इन प्राप्त कर सकते हैं में पैरामीटर और इन मानकों को सीधे अपने डब्ल्यूएस क्लाइंट को असाइन करने के लिए:

wss.on('connection', function connection(ws, req) { 

    const parameters = url.parse(req.url, true); 

    ws.uid = wss.getUniqueID(); 
    ws.chatRoom = {uid: parameters.query.myCustomID}; 
    ws.hereMyCustomParameter = parameters.query.myCustomParam; 
} 
+0

इसका कहीं भी उल्लेख क्यों नहीं किया गया है? बहुत बढ़िया जवाब। – Sam

+0

पासिंग पैरामीटर सीधे मेरे लिए बहुत अच्छा समाधान है – Hylle

+0

क्या 'ws' को म्यूट किए बिना ऐसा करने का कोई तरीका है? 'Ws.clients.values ​​() 'करते समय, क्या उस सूची के अनुरोध को बंद करने का कोई तरीका है? – Sawtaytoes

0

यहां एक संभावित समाधान देवी को जोड़ सकता है उपयोगकर्ता आईडी के सामने सीआईआईडी, इसलिए हम एक ही उपयोगकर्ता आईडी के साथ कई अलग-अलग उपकरणों पर अलग-अलग उपयोगकर्ताओं को अलग करते हैं।

ws://xxxxxxx:9000/userID/<<deviceId>>

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