2011-12-11 119 views
8

當他們的套接字ID被直接存儲在io.sockets.on('connect')函數中時,我似乎只能向用戶發送消息。我不知道爲什麼想存儲他們的插座ID他們在登錄後,當它不工作通過它的socket.id發送消息給客戶端

工作:

不工作:

var clients = {}; 
    /** A new socket connection has been accepted */ 
    io.sockets.on('connection', function (socket) 
    { 
    //Used to access session id 
    var hs = socket.handshake;    
     clients[socket.id] = socket; // add the client data to the hash    

    socket.on('user-login', function(user){   
     if(!users['brownj2']){ 
     users['brownj2'] = socket.id; // connected user with its socket.id 
     } 
    }) 

    socket.on('page-load', function(pid) 
    { 
     if(users['brownj2']) 
     {   
     clients[users['brownj2']].emit('hello'); 
     } 
     else 
     { 
     console.log("NOT FOUND BROWNJ2"); 
     } 
    } 
    } 

JavaScript客戶端代碼片段

var socket = io.connect(''); 
socket.on("hello", function(){ 
    alert("Hi Jack"); 
    console.log("WEBSOCKET RECIEVED"); 
}) 

解決方案:由於@alessioalex 我不得不刪除從登錄頁面socket.io參考,並添加以下到io.sockets.on( '連接')

var hs = socket.handshake; 

sessionStore.get(hs.sessionID, function(err, session){ 
    console.log("SESSION: " + util.inspect(session)); 

    clients[socket.id] = socket; // add the client data to the hash 
    validUsers[session.username] = socket.id; // connected user with its socket.id 
}) 

回答

25

你的代碼有一些問題,首先你不應該通過Socket.IO來驗證用戶,你應該確保它們只有在通過驗證後才能連接。如果使用的是快遞,那麼下面的文章可以幫助你很多:http://www.danielbaulig.de/socket-ioexpress/

你也應該避免發送像這樣的消息,因爲這是Socket.IO的部分內部並可能改變:

io.sockets.socket(id).emit('hello'); 

相反,(如果你想將消息發送到特定的客戶端)最好是保持一個對象,例如與連接的客戶端(和刪除客戶端斷開連接後):

// the clients hash stores the sockets 
// the users hash stores the username of the connected user and its socket.id 
io.sockets.on('connection', function (socket) { 
    // get the handshake and the session object 
    var hs = socket.handshake; 
    users[hs.session.username] = socket.id; // connected user with its socket.id 
    clients[socket.id] = socket; // add the client data to the hash 
    ... 
    socket.on('disconnect', function() { 
    delete clients[socket.id]; // remove the client from the array 
    delete users[hs.session.username]; // remove connected user & socket.id 
    }); 
} 

// we want at some point to send a message to user 'alex' 
if (users['alex']) { 
    // we get the socket.id for the user alex 
    // and with that we can sent him a message using his socket (stored in clients) 
    clients[users['alex']].emit("Hello Alex, how've you been"); 
} 

當然,io.sockets.socket(id)可能工作(沒「實際上測試),但它也可以隨時更改,因爲它是Socket.IO內部的一部分,所以我上面的解決方案更「安全」。

你可能要在客戶端上的代碼改變的另一件事是var socket = io.connect('');var socket = io.connect('http://localhost');,因爲我們可以在這裏Socket.IO的官方例子中看到:http://socket.io/#how-to-use

+0

謝謝,它的工作原理然而,當我嘗試使用 socket.on( '登錄',......){用戶[U] = socket.id}這是行不通的。我似乎只能直接添加用戶在io.sockets.on('連接') – Jack

+1

你確定嗎?由於socket是一個定義在'above'上的變量,因此它也應該在該函數中可見,就像我在我的示例中顯示的斷開連接一樣。 – alessioalex

+1

我改變了這個問題,向你展示一個工作和非工作的例子。我無法弄清楚爲什麼它不允許我在上面的「非工作」示例中發送消息。 – Jack

2

我可以看到這個帖子產生相當多的興趣......所以我要發佈我用來實現這個代碼:我已經使用Redis的作爲會話存儲

。會話最初是通過包含用戶詳細信息的HTTP請求在登錄頁面中設置的,如果這些詳細信息是有效的(根據MongoDB文檔進行檢查)...則創建會話。

服務器端代碼創建和會話/插座的去除

//Auth the user 
io.set('authorization', function (data, accept) { 
    // check if there's a cookie header 
    if (data.headers.cookie) { 
    data.cookie = parseCookie(data.headers.cookie); 
    data.sessionID = data.cookie['express.sid']; 

    //Save the session store to the data object 
    data.sessionStore = sessionStore; 

    sessionStore.get(data.sessionID, function(err, session){ 
     if(err) throw err; 

     if(!session) 
     { 
     console.error("Error whilst authorizing websocket handshake"); 
     accept('Error', false); 
     } 
     else 
     { 
     console.log("AUTH USERNAME: " + session.username); 
     if(session.username){ 
      data.session = new Session(data, session); 
      accept(null, true); 
     }else { 
      accept('Invalid User', false); 
     } 
     } 
    }) 
    } else { 
    console.error("No cookie was found whilst authorizing websocket handshake"); 
    return accept('No cookie transmitted.', false); 
    } 
}); 

/** A new socket connection has been accepted */ 
io.sockets.on('connection', function (socket) 
{  
    var hs = socket.handshake; 
    if(hs.session) 
    { 
    if(hs.session.username) 
    { 
     clients[socket.id] = socket; // add the client data to the hash 
     validUsers[hs.session.username] = socket.id; // connected user with its socket.id 
    } 
    } 


    socket.on('disconnect', function() 
    { 
    delete browsing[hs.session.username]; //Remove the client from the browsing hash 
    delete clients[socket.id];   // remove the client from the array 
    delete validUsers[hs.session.username]; // remove connected user & socket.id 
    }) 
.... 
} 

服務器端可選擇的消息發送

此代碼可以讓我將消息發送到團隊項目的成員。一組用戶將不會收到來自單獨用戶組的消息。

for(var i = 0; i < project.team.length; i++) 
{ 
    if(validUsers[project.team[i].username]) 
    { 
    if(clients[validUsers[project.team[i].username]]) 
    { 
     projects.update({"_id" : projectId}, 
     {"$pull" : 
      {"stories" : {"_id" : storyId}} 
     } 
    );     
     clients[validUsers[project.team[i].username]].emit('delete-story', storyId); 
    } 
    else 
    { 
     console.error("Project team member not found"); 
    } 
    } 
} 
相關問題