上次說到關於socket鏈接受權的問題,有好心人提示說到session-socket開源項目,能夠在創建鏈接後進行session相關操做,操做挺方便,很感謝這位朋友。個人目的是在握手階段,經過會話斷定權限,暨是否創建鏈接,因此只能本身查閱中間件代碼,而後COPY須要的。javascript
Connect相關的會話存儲我知道四種,cookie-based,memory-store,redis,mongodb.java
cookie-based方案數據直接存儲在cookie裏面,解析以後便可得到。node
memory-store方案,使用內存作容器,來存儲數據,因爲中間件使用了閉包特性,若是不對中間件動手腳的話,是沒法訪問這些數據,並且我是Express和socket.io分離的,更不可能拿到數據,因此此路不通。redis
connect-redis方案,將數據放入redis數據庫,這樣不一樣進程均可以獲取到session數據。Cookie解析以後獲取sessionId,經過sessionId從redis獲取數據。mongodb
mongodb方案,跟redis機理相同,再也不贅述。數據庫
var express =require('express'); var app = express(); var RedisStore = require('connect-redis')(express); app.use(express.cookieParser('love')); app.use(express.session({key: 'lovestory', secret: 'lovestory', store: new RedisStore({ host: '127.0.0.1', port: 6379}) }));
var io = require('socket.io').listen(1338); var utils = require('connect/lib/utils.js'); var cookie = require('connect/node_modules/cookie-parser/node_modules/cookie'); var redis = require('redis'); var client = redis.createClient(6379,'127.0.0.1'); //鏈接受權斷定,相關參數須要跟啓用Session的參數相同 io.sockets.authorization(function (handshakeData, callback) { //cookie解析,獲取sessionId var cookies = handshakeData.headers.cookie; var secret = 'lovestory'; var key = 'lovestory'; var prefix = 'sess:'; var sessionId = null; if (cookies) { cookies = cookie.parse(cookies); cookies = utils.parseSignedCookies(cookies, secret); cookies = utils.parseJSONCookies(cookies); if(cookies[key]) { sessionId = cookies[key]; } } //從redis獲取數據 var sid = prefix + sessionId; client.get(sid,function(err,data){ var result = JSON.parse(data); if (result.user){ for (var i in handshakeData) { delete handshakeData[i]; } handshakeData.user = result.user; callback(null,true); }else{ callback(null,false); } }); }); //存儲user,socketId鍵值對,須要單點推送的時候經過user獲取對應的socketId便可。 io.sockets.on('connection', function (socket) { client.set(socket.handshake.user,socket.id); io.sockets.socket(socket.id).send('Do you love this girl!!!'); });
var express =require('express'); var app = express(); app.use(express.cookieParser('lovestory')); app.use(express.cookieSession({key: 'lovestory', secret : 'lovestory'});
var io = require('socket.io').listen(1338); var utils = require('connect/lib/utils.js'); var cookie = require('connect/node_modules/cookie-parser/node_modules/cookie'); //鏈接受權斷定,相關參數須要跟啓用Session的參數相同 io.sockets.authorization(function (handshakeData, callback) { //cookie解析,獲取cookie中的session數據 var cookies = handshakeData.headers.cookie; var secret = 'lovestory'; var key = 'lovestory'; if (cookies) { cookies = cookie.parse(cookies); cookies = utils.parseSignedCookies(cookies, secret); cookies = utils.parseJSONCookies(cookies); if(cookies[key]) { session = JSON.parse(cookies[key]); } } });
上述代碼比較原始,由於基本上是COPY出來的,不過能夠實現我最初的想法。可是新問題也冒出來了,我如何得知,何時,須要向哪些用戶,推送什麼消息。例如SNS,一位用戶更新了狀態,須要推送給他的朋友,就是須要主動向瀏覽器端推送消息的時候,如何通知到這個進程。。。。。。。express
Websocket握手階段是經過HTTP協議完成的,socket.io負責監聽upgrade,connection事件,能夠與普通HTTP server共存。經過HTTP模塊監聽普通http請求,當業務邏輯進程完成相應工做,斷定須要向其餘用戶推送消息時,向推送進程發出http請求,附帶需推送內容便可。json
業務邏輯進程與推送進程創建socket鏈接,當業務邏輯進程完成相應工做,斷定須要向其餘用戶推送消息時,經過socket發送消息便可。瀏覽器
var http = require('http'); var app = http.createServer(function(req,res){}); var io = require('socket.io').listen(app); app.listen(1338);
HTTP請求body部分目測須要包含如下信息。
服務器
字段 | 功能 |
---|---|
type |
必需。single ,room ,或all ,對應單點推送,羣組推送,全局推送 |
pointer |
必需。指明須要推送的目標,若type 爲all ,顯式聲明true |
content |
必需。指明須要推送的內容 |
事件監聽函數(請原諒個人大嵌套~~|||)
function(req,res){ jsonBody(req,res,function(err,data){ if(err) { res.statusCode = 400; res.end('Bad request, json body only'); }else{ if (data.type && data.pointer && data.content) { switch (data.type) { case 'all' : io.sockets.send(data.content); res.end('success'); break; case 'room' : io.sockets.in(data.pointer).send(data.content); res.end('success'); break; case 'single' : client.get(data.pointer, function(err,result){ if(result) { io.sockets.socket(result).send(data.content); res.end('success'); } }) default : res.end('unexpected type'); break; } }else{ res.end('Bad request!'); } } }) }
代碼還欠缺不少打磨,不過基本功能已經出來了。
到此爲止,socket.io常規使用已經所有over,涉及到的相關代碼私下繼續打磨。