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