微信小程序server-3-搭建WebSocket 服務

ZHIHU:WebSocket是什麼,基於什麼原理?爲何能夠實現持久鏈接?node

1.安裝 Node 模塊

使用 ws 模塊來在服務器上支持 WebSocket 協議,下面使用 NPM 來安裝:nginx

cd /var/www/wxpro
npm install ws --save

2.實現 WebSocket 服務器

建立 websocket.js,實現 WebSocket 服務web

// 引入 ws 支持 WebSocket 的實現
const ws = require('ws');

// 導出處理方法
exports.listen = listen;

/**
 * 在 HTTP Server 上處理 WebSocket 請求
 * @param {http.Server} server
 * @param {wafer.SessionMiddleware} sessionMiddleware
 */
function listen(server, sessionMiddleware) {
    // 使用 HTTP Server 建立 WebSocket 服務,使用 path 參數指定須要升級爲 WebSocket 的路徑
    const wss = new ws.Server({ server, path: '/ws' });

    // 監聽 WebSocket 鏈接創建
    wss.on('connection', (ws,request) => {// 要升級到 WebSocket 協議的 HTTP 鏈接

        // 被升級到 WebSocket 的請求不會被 express 處理,
        // 須要使用會話中間節獲取會話
        sessionMiddleware(request, null, () => {
            const session = request.session;
            if (!session) {
                // 沒有獲取到會話,強制斷開 WebSocket 鏈接
                ws.send(JSON.stringify(request.sessionError) || "No session avaliable");
                ws.close();
                return;
            }
            // 保留這個日誌的輸出可以讓實驗室能檢查到當前步驟是否完成
            console.log(`WebSocket client connected with openId=${session.userInfo.openId}`);
            serveMessage(ws, session.userInfo);
        });
    });

    // 監聽 WebSocket 服務的錯誤
    wss.on('error', (err) => {
        console.log(err);
    });
}

/**
 * 進行簡單的 WebSocket 服務,對於客戶端發來的全部消息都回復回去
 */
function serveMessage(ws, userInfo) {
    // 監聽客戶端發來的消息
    ws.on('message', (message) => {
        console.log(`WebSocket received: ${message}`);
        ws.send(`Server: Received(${message})`);
    });

    // 監聽關閉事件
    ws.on('close', (code, message) => {
        console.log(`WebSocket client closed (code: ${code}, message: ${message || 'none'})`);
    });

    // 鏈接後立刻發送 hello 消息給會話對應的用戶
    ws.send(`Server: 恭喜,${userInfo.nickName}`);
}

編輯 app.js,調用 WebSocket 服務mongodb

// HTTP 模塊同時支持 Express 和 WebSocket
const http = require('http'); 
// 引用 express 來支持 HTTP Server 的實現
const express = require('express');
// 引用 wafer-session 支持小程序會話
const waferSession = require('wafer-node-session'); 
// 使用 MongoDB 做爲會話的存儲
const MongoStore = require('connect-mongo')(waferSession); 
// 引入配置文件
const config = require('./config'); 
// 引入 WebSocket 服務實現
const websocket = require('./websocket');

// 建立一個 express 實例
const app = express();

// 獨立出會話中間件給 express 和 ws 使用
const sessionMiddleware = waferSession({
    appId: config.appId,
    appSecret: config.appSecret,
    loginPath: '/login',
    store: new MongoStore({
        url: `mongodb://${config.mongoUser}:${config.mongoPass}@${config.mongoHost}:${config.mongoPort}/${config.mongoDb}`
    })
});
app.use(sessionMiddleware);

// 在路由 /me 下,輸出會話裏包含的用戶信息
app.use('/me', (request, response, next) => { 
    response.json(request.session ? request.session.userInfo : { noBody: true }); 
    if (request.session) {
        console.log(`Wafer session success with openId=${request.session.userInfo.openId}`);
    }
}); 

// 實現一箇中間件,對於未處理的請求,都輸出 "Response from express"
app.use((request, response, next) => {
    response.write('Response from express');
    response.end();
});

// 建立 HTTP Server 而不是直接使用 express 監聽
const server = http.createServer(app);

// 讓 WebSocket 服務在建立的 HTTP 服務器上監聽
websocket.listen(server, sessionMiddleware);

// 啓動 HTTP 服務
server.listen(config.serverPort);

// 輸出服務器啓動日誌
console.log(`Server listening at http://127.0.0.1:${config.serverPort}`);

3.編輯 Nginx 配置 ssl.conf,添加 WebSocket 支持

#WebSocket 配置
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
        listen 443;
        server_name www.example.com; # 改成綁定證書的域名
        #ssl 配置
        ssl on;
        ssl_certificate 1_www.example.com.crt; # 改成本身申請獲得的 crt 文件的名稱
        ssl_certificate_key 2_www.example.com.key; # 改成本身申請獲得的 key 文件的名稱
        ssl_session_timeout 5m;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
        ssl_prefer_server_ciphers on;

        #WebSocket 配置
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        location / {
            proxy_pass http://127.0.0.1:8765;
        }
    }
nginx -t
nginx -s reload
相關文章
相關標籤/搜索