如题,用node express搭建一个简易的websocket服务器。
项目开始
首先,按照官方教程( express生成器)搭建一个express项目出来。
项目目录应该如下(utils是我自己加的,后面会讲到):

然后 npm install ws
, 安装ws模块。安装完成后在package.json里面应该可以看到这个。

在bin/www.js
文件中,对照着下面的中文注释加一些代码。
var app = require('../app');
var debug = require('debug')('shot-trail-backend:server');
var http = require('http');
var ws = require('ws'); // 加入引入ws模块的代码。
var wsUtils = require('../utils/websocket');
/**
* Get port from environment and store in Express.
*/
var port = normalizePort(process.env.PORT || '3000'); // normalizePort只是个安全保证,如果可以保证提供的端口一定是数字或者是可以转换成数字的字符串,那么可以不用这个。
app.set('port', port);
/**
* Create HTTP server.
*/
var server = http.createServer(app); // http服务器
var wsServer = new ws.Server({ // 加入创建ws服务器的代码。
port: 80,
server: server // 注意这个server选项,要么挂载在一个已有的http服务器中,要么它会自己创建一个。
// 这边已经有一个http服务器了,所以我们填上,进行挂载就行了。
});
/**
* Listen on provided port, on all network interfaces.
*/
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
wsServer.on('connection', function (websocket) { // 加入这段代码,对连接之后的websocket连接进行配置。
websocket.on('error', onError); // 监听对应事件。
websocket.on('open', onOpen);
websocket.on('close', onClose);
websocket.on('message', onMessage);
wsUtils.init(websocket); // 这边的init函数稍后说明。
});
/**
* Normalize a port into a number, string, or false.
*/
好了,websocket服务器就搭好了。超级简单的有木有。
跑项目:输入 npm run start(自己在package.json重新配置过script自己输自己的命令),然后就可以在客户端用下面的代码连接了:
let websocket = new WebSocket('ws://localhost:80/');
进行消息推送
实际上知道的都觉得很简单,就是在建立websocket服务器之后,在监测到connection的时候用send方法就好了。
wsServer.on('connection', function (websocket) { // 加入这段代码,对连接之后的websocket连接进行配置。
websocket.on('error', onError); // 监听对应事件。
websocket.on('open', onOpen);
websocket.on('close', onClose);
websocket.on('message', onMessage);
// 这个位置用send方法就行了。
wsUtils.init(websocket); // 这边的init函数稍后说明。
});
但是,怎么在用户调用了一个接口之后,就进行推送呢?
这时候要先把连接建立好之后,生成的websocket实例保存下来,就是下面这张图片里的函数参数对应的对象要保存下来。

我把它通过闭包的方式存了下来。
首先在项目根目录建立utils文件路径,下面放一个websocket.js文件。

然后在websocket.js里面写上下面的代码,把其中的几个函数导出。
var wsServer = null;
function init (ws) {
wsServer = ws;
}
function send (message) {
if (!wsServer) return;
wsServer.send(message);
}
module.exports = { send, init };
之后在bin的www.js
文件中导入init函数。
var wsUtils = require('../utils/websocket.js');
在连接建立之后,调用init方法。
wsServer.on('connection', function (websocket) { // 加入这段代码,对连接之后的websocket连接进行配置。
....
wsUtils.init(websocket); // 调用init方法,保存websocket实例
});
然后就可以在express的其他route里面去推送信息了。例如在routes/index.js文件中:
var express = require('express');
var router = express.Router();
var wsUtils = require('../utils/websocket');
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
wsUtils.send(JSON.stringify('嗯嗯嗯'));
});
module.exports = router;
然后客户端就可以收到嗯嗯嗯了, 不过前提是连接已经建立了。
缺点
这样子的话,确实可以实现在客户调用其他接口的时候,进行推送,不过如果有多个websocket连接的话,不能区分,而且只能保留一个。或许可以用map加上用户标示区分一下。
网友评论