您现在的位置:首页 >> 前端 >> 内容

express redis socket消息提醒方案说明

时间:2018/4/8 13:54:32 点击:

  核心提示:express redis socket 消息提醒方案:本地emit 轮循服务器获取redis 再推送在做项目时,需要实现消息提醒,因为现在有多个项目,都需要实现。为了实现多项目公用,和以后项目也可以...

express redis socket 消息提醒方案:本地emit 轮循服务器获取redis 再推送

在做项目时,需要实现消息提醒,因为现在有多个项目,都需要实现。

为了实现多项目公用,和以后项目也可以使用。

单独开了个项目,起了个node 服务来实现消息提醒。

用express redis socket.io来实现的。

session 都存在redis里,所有的服务都一样。这样实现了,sessio共享

只要其他项目登录了,消息服务也就登录了。

因为要多个项目共用,所以会在项目中引用socket.io js 然后创建

var socket=io('https://localhost:8007');

链接到8007也就是消息服务器。

消息服务ioconnection 链接上后,通过socket.request.headers.sookie 来获取请求的cookie 找到connect.sid 得到sid。

再从redis上查找对应的用户信息。保存到链接socket上。然后发送emit open ,表示链接成功。

本地接收到后轮循向服务器发请message 请求来获取消息。

服务器查询redis获取消息,并emit 返回。

以下是服务端代码:

/*star 2016-8-20  
socket 从请求中获取cookie 也就是token 再从redis里取到token对应的user 信息。  
这后向socket页面emit(open) 表示当前登录用户链接socket成功。  
本地轮循发起emit message 事件,获取用户的提示条数。  
服务器根据 userid 从redis里读取提示条数并返回。  
----此为node socket 消息服务器第一种解决方案  
*/  
var express = require('express');  
var path = require('path');  
var cookieParser = require('cookie-parser');  
var bodyParser = require('body-parser');  
var session = require('express-session');  
var RedisStore = require('connect-redis')(session);  
var http = require('http');  
  
var redis_api=require('./redis_api.js')  
  
  
var port=8007;  
var app = express();  
  
  
  
// view engine setup  
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: false }));  
app.use(cookieParser());  
app.use(express.static(path.join(__dirname, 'public')));  
  
// 设置 Session  
app.use(session({  
  store: new RedisStore({  
    host: "127.0.0.1",  
    port: 6379,  
    db: 0  
    //pass: 'yu'  
  }),  
  resave:false,  
  saveUninitialized:false,  
  secret: 'keyboard cat'  
}))  
  
app.use(function(req,res,next){  
  console.log(req.url);  
  next();  
})  
  
  
  
  
app.get('/socket',function(req,res){  
    res.header("Access-Control-Allow-Origin", "*");  
    //console.log(req.session.username)  
    res.send(req.session)  
})  
  
  
var server = http.createServer(app);  
  
server.listen(port);  
server.on('error', onError);  
server.on('listening', onListening);  
  
  
var io=require('socket.io')(server);  
var users=[]  
io.on('connection',function(socket){      
    console.log('open')  
    //获取请求cookie  
    var cookie_string=decodeURIComponent(socket.request.headers.cookie)  
    //正则匹配 获取sid  
    var s=/connect.sid=([^\.]+)/g.exec(cookie_string);  
    var sid='';  
    if(s && s.length>1){  
        sid=s[1].split(':')[1];  
        //console.log(sid);  
        var user;  
        redis_api.getsid(sid,function(err,res){  
            if(!err){  
                user=res;             
                socket.emit('open',{sid:sid,user:user.user})  
                socket.sid=sid;  
                socket.user=user.user;  
                //链接数测试  
                /*var n=9000000;  
                while(n--){  
                    users.push(socket);  
                }*/  
            }  
        })  
    }  
    socket.on('message',function(res){  
        console.log(res);  
        switch(res.action){  
            case "read":  
                read();  
                break;  
        }  
    })  
    function read(){  
        redis_api.getmessage(socket.user.id,function(err,reply){  
            if(!err){  
                socket.emit('message',{type:1,action:'message',data:reply,number:users.length})  
            }  
        })  
    }  
    socket.on('disconnect',function(){  
        console.log('close')  
    })  
      
})  
  
function onError(error) {  
  if (error.syscall !== 'listen') {  
    throw error;  
  }  
  
  var bind = typeof port === 'string'  
     'Pipe ' + port  
    : 'Port ' + port;  
  
  // handle specific listen errors with friendly messages  
  switch (error.code) {  
    case 'EACCES':  
      console.error(bind + ' requires elevated privileges');  
      
      break;  
    case 'EADDRINUSE':  
      console.error(bind + ' is already in use');  
        
      break;  
    default:  
      throw error;  
  }  
}  
  
/**  
 * Event listener for HTTP server "listening" event.  
 */  
  
function onListening() {  
  
 console.log('localhost:'+port)  
}  

以下是redis_api代码

var redis   = require('redis');  
var client  = redis.createClient('6379', '127.0.0.1');  
  
  
exports.getsid=function(sid,call){  
    //client.select('0',function(err){            
            //if(!err){  
                //console.log('select 0',err)  
                client.get('sess:'+sid ,function(err,reply){  
                    console.log('------sess:'+sid)  
                    console.log('sess:',sid,err,reply)  
                    console.log('end ------sess:'+sid)  
                    if(err){  
                        call(err)  
                    }else{  
                        //console.log('sess:'+sid+'=',reply)  
                        call(0,JSON.parse(reply))  
                    }                     
                })  
            //}  
    //})  
  
}  
//根据userid 获取消息数  
exports.getmessage=function(userid,call){  
    client.select('0',function(err){  
        if(!err){  
            client.get('message:'+userid,function(err,reply){  
                if(!err){  
                    console.log('message:'+userid+'='+reply)  
                    call(0,JSON.parse(reply))  
                }  
                // 关闭链接  
                //client.quit();  
            })  
        }  
    })  
}  

以下是页面代码:

var socket=io('https://localhost:8007');  
            socket.on('open',function(res){  
                console.log('开了',res)  
                time();  
                //socket.emit('message',{id:1,type:1,action:'read'})  
            })  
            socket.on('message',function(res){  
                console.log(res,new Date());  
            })  
  
              
            //以下为轮循发请emit 获取消息数  
            function time(){  
                setInterval(function(){  
                    socket.emit('message',{type:1,action:'read'})  
                    //socket.emit('message',{type:1,action:'read'})  
                },3000)  
            }  

当然这种实现是有问题 的,并不是时时消息提醒。

而且当链接数大时不断轮循会给服务器和带宽带来很大压力。

Tags:EX XP PR RE 
作者:网络 来源:一涵的博客