[英]Socket.IO Emit is emitting to all clients
因此,我正在用NodeJS編寫應用程序,並在開始提出我的問題之前,請先了解我的設置當前的工作方式:
我有一些客戶端,它們通過Socket.io連接到“服務器X”,然后我的“服務器X”通過Socket.io連接到“服務器Y”,它們都通過Socket.io向彼此發送數據。
客戶端<--->服務器X <--->服務器Y
客戶端引用用戶及其瀏覽器,然后我在服務器x和服務器y上都運行了一個節點應用程序。
因此,在下面的我的服務器X上的代碼中,如果您看一下第4行,它完全可以正常工作。 它僅將消息發送給請求它的客戶端。
io.on('connection', function(socket){
// This works just fine.
socket.emit('return_login', 'Test Message');
socket.on('login', function(data){
// This line correctly sends the data to Server Y
server_y.emit('login', data);
});
server_y.on('return_login', function(data){
// This emits to all connected clients???
socket.emit('return_login', data);
});
});
現在我的問題是,當“服務器Y”向服務器x發出return_login
,我想讓服務器x接收服務器y發出的值,然后將其發送回原始客戶端或Web瀏覽器。 但是由於某種原因,該線路會發射到所有連接的客戶端。
我有一台筆記本電腦,這台計算機和我的手機都對此進行了測試,並且每次發射時都會發送給每個人。
如果有人可以幫助我,我將不勝感激。 如果我需要發布更多代碼,請告訴我。
我不確定您的代碼。 但是我通常使用空間向用戶發出套接字的回調函數。 這是我使用回調而不是return_login事件的解決方案
io.on('connection', function(socket){ socket.on('login', function(data, callback){ // Using callback instead of return_login event server_y.emit('login', data, function(responseData){ // put this socket to room as name = user_id socket.join(responseData.user_id); // return result by callback callback(responseData) }); }); }); // emit to exactly user_id with return_login event if you want io.to(user_id).emit('return_login', {key: 'ok'})
它正在發送給所有客戶端,因為您已經為return_login
消息的每個套接字安裝了單獨的偵聽器。 因此,當一個客戶端登錄並將return_login
消息發送回服務器時,每個看到該消息並將其轉發到該套接字的套接字都具有一個單獨的偵聽器。 這樣,它將發送到每個連接的套接字。
解決該問題的一種方法是確保將return_login
消息僅發送到它所屬的套接字。 如果可以發送帶有該消息的socket.id,並讓該服務器作為響應的一部分回顯該ID,則可以檢查是否在收到消息時確保僅將其發送到它所屬的套接字。
這是純基於消息的系統的問題之一。 您正在嘗試執行僅請求者看到響應的請求/響應,但是socket.io不是請求/響應系統。 響應將發送給該特定消息的所有偵聽器,並且由於您為連接的每個套接字都具有該消息的偵聽器,因此每個套接字都可以看到該消息,然后將其轉發到其客戶端。
因此,通過對另一台服務器進行相應的修改以回顯id
值,您可以執行以下操作:
io.on('connection', function(socket){
// This works just fine.
socket.emit('return_login', 'Test Message');
socket.on('login', function(data){
// add our id so we can identify our response back
data.id = socket.id;
server_y.emit('login', data);
});
let fn = function(data) {
// check to see if this message is destined for this socket
if (data.id === socket.id) {
// make data copy with id value removed so
// we don't send that to the client
let tempData = Object.assign({}, data);
tempData.delete(id);
socket.emit('return_login', tempData);
// we're done with this listener so remove it
server_y.removeListener('return_login', fn);
}
});
server_y.on('return_login', fn);
});
收到消息后,只為return_login
消息刪除偵聽器可能很誘人,但是如果兩個客戶端恰巧同時在登錄過程中並且因此兩個客戶端同時具有偵聽器,則會導致爭用情況,那么兩個偵聽器都會收到第一條消息。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.