socket.io一對一通信的實現

socket.io網上有很多例子,但是大多數都是聊天室的,沒有找到一對一通信的例子

百度搜索了一下,在oschina裏面看到了一篇文章http://www.oschina.net/question/190778_164263?sort=time

給了一點思路,就是每次用戶連上socket的時候,保存一個id映射到socket對象的鍵值對

然後在每次emit新消息的時候,根據客戶端傳來的id,獲取對應的socket對象,用這個對象emit信息,就可以實現一對一通信了

下面貼一下我的關鍵實現代碼,代碼基於上次發的文章的代碼https://github.com/xyc-cn/socket-angular/tree/xyc_3

1.首先得在socket驗證登陸的時候,把user對象傳進來,前提是你在req.session.user裏面添加了你的user對象

var io= require("socket.io").listen(app.listen(8000));
io.set('authorization', function(handshakeData, accept) {
     var cookies = cookie.parse(handshakeData.headers.cookie);
     var connectSid = cookies['connect.sid'];
     if(connectSid){
     var connected = cookieParser.signedCookie(connectSid, 'technode');
     if(connected){
     sessionStore.get(connected, function (error, session) {
     if (error) {
     accept(error.message, false)
     } else {
     handshakeData.headers.sessions  = session;//根據connectSid找session如果session對象不爲空,把session對象添加到socket的headers裏面
     if (session.user) {
     accept(null, true)
     } else {
     accept(null,false)
         }
     }
     })
 }else {
    accept(null,false)
    }
 }

 });
2.在socket鏈接的時候,我在客戶端emit了init,在服務端保存id映射到socket對象的鍵值對
var loginUser = new Object();
socket.on('init', function () {
        socket.emit('init', messages);
        if(socket.handshake.headers.sessions!=null){//如果sessions不爲空,取出裏面保存的user對象
            var user = socket.handshake.headers.sessions.user;
            loginUser[user._id] = socket;//建立id映射到socket對象的鍵值對
            UserModel.modify({account:user.account},{status:1},function(err,doc){//這部分是我獲取在線用戶的代碼
                UserModel.User.find({status:1},{account:1}, function (err,doc) {
                    if(doc){
                        io.sockets.emit('users.init', doc);
                    }
                });
            });

        }
    });
3.新建消息的時候,客戶端傳來一個belong,告訴服務端,這條消息是屬於哪兩個人的,這個值必須是唯一的,我是把兩個通信的人的ID加起來生成這個值,然後還要傳來to告訴服務器這個消息是發給誰的,from告訴服務器這個信息是誰發出來的

socket.on('messages.create', function (message) {
        var data ={};
        data.content = message.content;
        data.account = message.account;
        data.belong = message.belong;
        var to= message.to;

        MessageModel.create(data,function (err,doc) {//新建數據庫條目
            if(!err){
                socket.emit('messages.add',doc,to,message.from);//emit通知自己,在發送方的窗口新增他自己發送的消息
                if(loginUser[to]!=null){//根據to值,選擇對應的socket對象
                    loginUser[to].emit('messages.add', doc,to,message.from);//如果找到了這個對象,就emit信息給這個socket對象的鏈接客戶端,傳遞信息
                }
            }
        });
    });
4.客戶端讀取信息的時候,要傳來一個belong值,告訴服務端讀取哪些聊天記錄

 socket.on('messages.read', function (belong) {
        MessageModel.getMessage(new Date(),belong,function(err,doc){//根據傳來的belong值,獲取對應的聊天記錄
            socket.emit('messages.read', doc);
        });
    });
5.鏈接斷開的時候,清空數據

socket.on('disconnect', function() {
        if(socket.handshake.headers.sessions!=null) {
            var user = socket.handshake.headers.sessions.user;
            loginUser[user.id]=null;//清空對應的鍵值對
            UserModel.modify({account: user.account}, {status: 0}, function (err, doc) {//用戶狀態設置爲下線
                if (doc != null) {
                    console.log(doc.account + " has disconnect");
                }
            });
            socket.broadcast.emit('users.remove', user);
        }
    });

整個項目的代碼在https://github.com/xyc-cn/socket-angular/tree/xyc_4

有問題或者建議歡迎Q我278255596



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章