2011-12-11 4 views
8

Tôi chỉ có thể phát ra tin nhắn cho người dùng khi id ổ cắm của họ đã được lưu trữ trực tiếp trong hàm io.sockets.on ('connect'). Tôi không biết tại sao nó không hoạt động khi cố gắng lưu trữ id ổ cắm của họ sau khi họ đã đăng nhậpGửi tin nhắn cho khách hàng qua socket.id

làm việc:.

Không làm việc:

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

Đoạn mã JavaScript phía máy khách

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

Giải pháp: Cảm ơn @alessioalex tôi đã phải loại bỏ các tham chiếu đến socket.io từ trang đăng nhập, và thêm đoạn mã sau vào io.sockets.on ('kết nối')

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

Trả lời

25

Có một số vấn đề với mã của bạn, đầu tiên là bạn không nên xác thực người dùng thông qua Socket.IO, bạn nên đảm bảo rằng họ có thể kết nối chỉ sau khi họ được xác thực. Nếu bạn đang sử dụng Express, thì bài viết sau đây có thể giúp bạn rất nhiều: http://www.danielbaulig.de/socket-ioexpress/

Ngoài ra bạn nên tránh gửi tin nhắn như vậy, vì đó là một phần của Socket.IO nội bộ và có thể thay đổi:

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

Thay vào đó (nếu bạn muốn gửi một thông điệp tới một khách hàng cụ thể) nó tốt hơn để giữ một đối tượng ví dụ với các khách hàng kết nối (và loại bỏ các khách hàng khi ngắt kết nối):

// 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"); 
} 

chắc chắn, io.sockets.socket(id) có thể làm việc (didn ' t thực sự thử nghiệm), nhưng cũng có thể nó luôn luôn thay đổi vì nó là một phần của Socket.IO internals, vì vậy giải pháp của tôi ở trên là an toàn hơn.

Một điều bạn có thể muốn thay đổi trong mã của bạn trên các mặt hàng là var socket = io.connect(''); với var socket = io.connect('http://localhost');, như chúng ta có thể thấy trong ví dụ chính thức của Socket.IO đây: http://socket.io/#how-to-use

+0

Cảm ơn, nó hoạt động tuy nhiên khi tôi cố gắng sử dụng socket.on ('đăng nhập', .....) {người dùng [u] = socket.id} nó không hoạt động. Tôi chỉ có thể thêm người dùng trực tiếp vào trong io.sockets.on ('kết nối') – Jack

+1

Bạn có chắc chắn không? Vì socket là một biến được định nghĩa là 'ở trên', nên nó cũng sẽ được hiển thị trong hàm đó, giống như tôi hiển thị trong ví dụ của tôi khi ngắt kết nối. – alessioalex

+1

Tôi đã sửa đổi câu hỏi để hiển thị cho bạn một ví dụ hoạt động và không hoạt động. Tôi không thể hiểu tại sao nó sẽ không cho phép tôi gửi tin nhắn trong ví dụ 'không hoạt động' ở trên. – Jack

2

Tôi có thể thấy rằng bài này được tạo ra khá nhiều sự quan tâm ... do đó, tôi sẽ gửi mã tôi đã sử dụng để thực hiện điều này:

Ghi chú

tôi đã sử dụng Redis như việc lưu trữ phiên. Phiên này ban đầu được thiết lập trong trang đăng nhập thông qua một yêu cầu HTTP chứa các chi tiết người dùng, nếu các chi tiết này hợp lệ (được kiểm tra dựa trên tài liệu MongoDB) ... thì phiên được tạo.

Server Side Mã Creation và diệt của phiên/Socket

//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 
    }) 
.... 
} 

Server Side Selective nhắn Gửi

Mã này cho phép tôi gửi một thông điệp cho các thành viên của dự án. Một nhóm người dùng sẽ không nhận được tin nhắn từ một nhóm người dùng riêng biệt ..

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