Socket.io 学习笔记三

韩瑶
• 阅读 9899

Socket.io 学习笔记三

前言

上次说到关于socket连接授权的问题,有好心人提示说到session-socket开源项目,可以在建立连接后进行session相关操作,操作挺方便,很感谢这位朋友。我的目的是在握手阶段,通过会话判定权限,暨是否建立连接,所以只能自己查阅中间件代码,然后COPY需要的。

Connect Session

Connect相关的会话存储我知道四种,cookie-based,memory-store,redis,mongodb.

  • cookie-based方案数据直接存储在cookie里面,解析之后即可获得。

  • memory-store方案,使用内存做容器,来存储数据,由于中间件使用了闭包特性,如果不对中间件动手脚的话,是无法访问这些数据,而且我是Express和socket.io分离的,更不可能拿到数据,所以此路不通。

  • connect-redis方案,将数据放入redis数据库,这样不同进程都可以获取到session数据。Cookie解析之后获取sessionId,通过sessionId从redis获取数据。

  • mongodb方案,跟redis机理相同,不再赘述。

Connect-redis

  • 启用connect-redis session。
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})
}));
  • socket.io部分
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!!!');
});

Cookie-based更加简单一些

  • Express部分
var express =require('express');
var app = express();
app.use(express.cookieParser('lovestory'));
app.use(express.cookieSession({key: 'lovestory', secret : 'lovestory'});
  • socket.io部分
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,一位用户更新了状态,需要推送给他的朋友,就是需要主动向浏览器端推送消息的时候,如何通知到这个进程。。。。。。。

粗略构想(“进程”只为叙述方便,略有不妥)

  • Websocket握手阶段是通过HTTP协议完成的,socket.io负责监听upgrade,connection事件,可以与普通HTTP server共存。通过HTTP模块监听普通http请求,当业务逻辑进程完成相应工作,判定需要向其他用户推送消息时,向推送进程发出http请求,附带需推送内容即可。

  • 业务逻辑进程与推送进程建立socket连接,当业务逻辑进程完成相应工作,判定需要向其他用户推送消息时,通过socket发送消息即可。

简易实现

  • socket.io与普通HTTP服务同时存在
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 必需。指明需要推送的目标,若typeall,显式声明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连接,基本理念是相同的,就不再往坑里跳。

个人总结

到此为止,socket.io常规使用已经全部over,涉及到的相关代码私下继续打磨。

点赞
收藏
评论区
推荐文章
xiguaapp xiguaapp
4年前
tcp的三次握手四次挥手
tcp的三次握手流程:在tcp/ip协议中,tcp协议提供可靠的连接服务,采用三次握手建立一个连接。第一次握手:建立连接时,客户端发送SYN包【synj】到服务器,并进入SYN_SEND状态,等待服务器确认;第二次握手:服务器收到SYN包,必须确认客户的SYN(ackj1),同时自己也发送一个SYN包(syn
Wesley13 Wesley13
3年前
TCP三次握手的过程
TCP(TransmissioncontrolProtocol)是一种面向连接,可靠的,基于字节流的运输层通信协议,是专门为了在不可靠的互联网络上提供一个可靠的端到端字节流而设计的。每一次tcp连接需要3个阶段:连接建立,数据传送和连接释放三次握手发生在连接建立阶段,目的是为了防止已失效的连接请求报文端突然又传送到服务器端,因而产生错误三
Wesley13 Wesley13
3年前
TCP三次握手和四次挥手
建立TCP连接:三次握手TCP在传输数据之前,首先需要建立好TCP连接,后续所有数据都基于这个已建立的连接来传输,建立TCP连接的过程通常被描述为三次握手屏幕快照2020072716.44.59!TCP三次握手和四次挥手(https://s4.51cto.com/images/blog/202007/27/e095cdb6ee5e99
Easter79 Easter79
3年前
TCP三次握手与Linux的TCP内核参数优化
感谢各位技术大佬的资料分享,这里我把我理解的内容做一个整理一:TCP的三次握手1、TCP简述  TCP是一个面向连接的协议,在连接双方发送数据之前,首先需要建立一条连接。TCP建立连接可以简单称为:三次握手(说白了就是建立一个TCP连接的时候,客户端
Wesley13 Wesley13
3年前
TCP 的连接建立:采用三报文握手
!(https://img2018.cnblogs.com/blog/1201066/201812/120106620181228174356520732746810.png)!(https://oscimg.oschina.net/oscnet/42ecd7584eea1a294c0a85a74466d20729d.png)!(ht
Wesley13 Wesley13
3年前
TCP是如何实现三次握手的?
什么是三次握手1.TCP是网络传输层的协议,提供面向连接的可靠的字节流服务,要通信得先建立连接2.所谓三次握手就是指,建立一个TCP连接时,需要CLient与Server发送三个包,确认连接的建立3.这一过程由Client执行connect触发简单描述下三次握手的具体过程第一
Wesley13 Wesley13
3年前
Go语言 之TCP三次握手
所谓三次握手(ThreeWayHandshake)即建立TCP连接,就是指建立一个TCP连接时,需要客户端和服务端总共发送3个包以确认连接的建立。好比两个人在打电话:Client:“喂,你听得到吗?”Server:“我听得到,你听得到我吗?”Client:“我能听到你,今天balabala…”建立连接(三次握手)的过程:1.客户端
Wesley13 Wesley13
3年前
NIO入门之传统的BIO编程
网络编程的基本模型是Client/Server模型,也就是两个进程之间进行相互通信,其中服务端提供位置信息(绑定的IP地址和监听端口),客户端通过连接操作向服务器监听的地址发起连接请求,通过三次握手建立连接,如果连接建立成功,双方就可以通过网络套接字(Socket)进行通信。在基于传统同步阻塞模型开发中,ServerSocket负责绑定IP地址,启动监听
Stella981 Stella981
3年前
Linux应急响应(二):捕捉短连接
0x00前言​短连接(shortconnnection)是相对于长连接而言的概念,指的是在数据传送过程中,只在需要发送数据时,才去建立一个连接,数据发送完成后,则断开此连接,即每次连接只完成一项业务的发送。在系统维护中,一般很难去察觉,需要借助网络安全设备或者抓包分析,才能够去发现。0x01应急场景​
融云IM即时通讯 融云IM即时通讯
7个月前
融云IM干货丨客户端和服务端长连接是如何建立的?
客户端和服务端之间建立长连接的过程通常涉及以下几个步骤:连接建立:客户端首先发起连接请求至服务端。这个过程通常包括TCP的三次握手,确保连接的可靠性。控制层交互:在某些架构中,客户端在建立连接前需要与控制层进行交互,以获取合法标识(Token)和接入配置(
ELB UDP健康检查常见故障分析
UDP是面向非连接的一种协议,在发送数据前不会通过进行三次握手建立连接,UDP健康检查的实现过程如下: