前景:
我们在创建一个项目的时候,刚开始websocket的server端的端口和http的端口是分开的,但是在部署的时候,只能使用同一个端口,所以就需要将websocket端口绑定在httpServer
websocket是http升级而来的,可以和httpServer共用一个端口,那么代码中如何实现呢?npm的ws已经有此处代码:
https://www.npmjs.com/package/ws
大体就是在创建websocket的时候,使用的是http来创建,然后启动server.listen(port);下面是https的例子
const fs = require('fs');
const https = require('https');
const WebSocket = require('ws');
const server = https.createServer({
cert: fs.readFileSync('/path/to/cert.pem'),
key: fs.readFileSync('/path/to/key.pem')
});
const wss = new WebSocket.Server({ server });
wss.on('connection', function connection(ws) {
ws.on('message', function incoming(message) {
console.log('received: %s', message);
});
ws.send('something');
});
server.listen(8080);
但是,目前有个情况,就是我们在创建app的时候,一般会设置好多的参数,而且都会将其封装,然后exports的形式,在其他地方进行引用。
下面是一个例子,我们为了方便测试或者代码更模块化,会封装一层层的类,那么在如何实现呢?
思想就是:在创建server的时候,将其app传递过去,并且启动监听端口
//index.js
const { wsServer } = require('./wsServer');
const { server } = require('./server');
const { log } = require('./utils');
server.on('listening', () => {
log('http server listening');
});
wsServer.on('listening', () => {
log('websocket listening');
});
//server.js
const http = require('http');
const app = require('./app');
const server = http.createServer(app);
const port = 13005;
app.set('port', port);
server.listen(port);
exports.server = server;
//wsServer,js
const WebSocket = require('ws');
const { getMsg } = require('./wsConnection');
const { server } = require('./server');
const { errLog } = require('./utils');
const wsServer = new WebSocket.Server({ server });
exports.wsServer = wsServer;
wsServer.on('connection', (ws) => {
try {
ws.on('message', getMsg.bind(ws));
} catch (error) {
errLog(error);
}
});
//wsConntions.js
const { errLog } = require('./utils');
async function getMsg(msg) {
try {
const data = JSON.parse(msg);
switch (data.cmd) {
case 'login':
this.accessToken = data.accessToken;
this.send(JSON.stringify({ cmd: 'loginRes', code: '0' }));
break;
default:
break;
}
} catch (err) {
errLog(err);
}
}
exports.getMsg = getMsg;
//app.js
const express = require('express');
const notifyRouter = require('./routes/notify');
const app = express();
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
const started = new Date();
app.get('/', (_req, res) => {
const unit = 1000;
const uptime = (Date.now() - started.getTime()) / unit;
return res.json({ started, uptime });
});
app.use('/notify', notifyRouter);
module.exports = app;
下面讲解一下:getMsg.bind(ws)
代码,bind函数会将ws传递过去,并且在getMsg函数中可以用this来过去ws的值,在这里进行给ws赋值,为了后续的,循环所有在线的ws客户端,然后获取其中的值做准备,那么也将获取所有在线的ws给出,
const wsserver = require('../wsServer');
const { clients } = wsserver.wsServer;
for (const client of clients) {
if (WebSocket.OPEN === client.readyState) {
//处理函数,在这里可以获取到token,client.accessToken
client.send(JSON.stringify(info));
}
}