概念介紹
WebSocket鏈接區別于http協議,他是位于TCP上層的全雙工的協議,也就是說服務端可以主動的推送消息給客戶端。在一些實時更新數據的場景中比較適用。
koa是nodejs中較為流行服務端框架,經常被用來作為http服務端開發使用,本文就簡單介紹一下在koa框架下如何建立WebSocket鏈接,并且能夠在wss鏈接中獲取并使用http服務器中的會話信息。
基礎工具介紹
首先介紹一下我們在項目中使用的一些庫。
- 用戶會話管理中間件koa-session
- ws的nodejs庫ws
- ws設置外部http服務器所需模塊http
我們使用koa-session來對用戶的會話信息進行管理,然后將koa作為外部的http服務器,將wss鏈接和http的服務域做成一致的。然后在wss鏈接中獲取用戶會話信息進行業務操作。
實施細節
1. 配置會話
我們創建koa服務器實例之后,使用koa-session的中間件進行管理,具體如下
const Koa = require('koa');
const app = new Koa();
const session = require('koa-session');
const CONFIG = {
// 具體配置
};
app.use(session(CONFIG, app));
2. wss服務器使用外部http服務器
ws可以創建ws的服務器,使用區別于http的端口和路徑,為了復用http的端口,ws需要配置額外的服務器。如下:
const http = require('http'); // 如果是https則引入https模塊
const server = http.createServer(app.callback()); // app是koa的服務器實例
const wss = new WebSocket.Server({ clientTracking: false, noServer: true }); //不使用自身的server,使用外部http服務器
3. 在ws鏈接中獲取用戶會話信息
在外部的http服務器中監聽ws鏈接,并識別用戶會話信息,然后再處理后續業務。
server.on('upgrade', function (request, socket, head) {
// console.log('Parsing session from request...');
const context = app.createContext(request, {});
// context.session里面就是上下文的會話信息。可以用來識別用戶是否登錄
if (!context.session.isLoggedIn) {
console.log('尚未登錄,請先登錄');
socket.destroy();
return;
}
wss.handleUpgrade(request, socket, head, function (ws) {
wss.emit('connection', ws, request);
});
});
wss.on('connection', function connection(ws, request) {
const context = app.createContext(request, {});
ws.on('message', function incoming(e) {
// 接收到message,然后進行業務處理
});
});
主要的核心就是koa的app提供一個由request來獲取上下文信息的接口。即 app.createContext(requst, {})。在request里面有客戶端發送請求時攜帶的cookie信息。app就可以基于cookie獲取用戶的上下文會話。
總結
本文主要描述了如何實施wss服務器使用koa作為外部的http服務器,復用http的端口,然后在ws的鏈接中獲取上下文會話信息。其核心有兩個,1是在創建ws服務器時配置使用外部的http服務器,2是在ws鏈接中使用app的createContext接口獲取客戶端上下文會話。
復用http端口的好處是客戶端新建wss鏈接時不需要考慮跨域,而且可以獲取用戶的會話信息,在ws鏈接中進行更加復雜的業務處理。