实现基于Websocket的消息推送
基于Websocket的消息推送,大概问题可以分解为以下三点:
- 服务器端Websocket设置
- 客户端Websocket设置
- nginx代理的设置
先说Nginx的设置
所有资料都说在Nginx配置文件中的location下加入以下配置:
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
参考资料:
- nginx配置支持websocket
- websocket+前后端分离+https的nginx配置
- 使用nginx作为websocket的proxy server
- Nginx 作为 WebSockets 代理
再说客户端设置
首先说发现的一个好东西,用TS改写Express模板,地址在这里。
再说正题,先在package.json中引入要用的Websocket包。
"express-ws": "~3.0.0"
在Express的目录结构里的bin/www
中加入以下代码:
let server = http.createServer(app);
const WSRouter = require('../routes/ws-router.js');
let wsRouter = WSRouter.init(server);
wsRouter.lintenClientConnect();
显而易见,主体部分在ws-router
中:
"use strict";
exports.__esModule = true;
var express = require("express");
var expressWS = require("express-ws");
var wsRouter = null;
var WSRouter = (function () {
function WSRouter(server) {
this.server = null;
this.app = null;
this.clients = [];
this.server = server;
this.app = express();
expressWS(this.app, this.server);
}
WSRouter.prototype.lintenClientConnect = function () {
var me = this;
this.app.ws('/', function (ws, req) {
console.log("client connect to server successful!");
me.clients.push(ws);
ws.on('message', function (msg) {
console.log("receive client msg :", msg);
me.receiveCmd(msg);
me.sendCmd(msg, 1);
});
ws.on("close", function (msg) {
console.log("client is closed");
for (var index = 0; index < me.clients.length; index++) {
if (me.clients[index] == this) {
me.clients.splice(index, 1);
}
}
});
});
};
WSRouter.prototype.sendCmd = function (msg, cb) {
for (let cell in this.clients) {
this.clients[cell].send('Hello world!');
}
};
WSRouter.prototype.receiveCmd = function (cmd) {
};
return WSRouter;
}());
function init(server) {
if (wsRouter == null && server != null) {
wsRouter = new WSRouter(server);
}
return wsRouter;
}
function sendMsg(msg){
wsRouter.sendCmd(msg, '');
}
module.exports = {
init: init,
sendMsg: sendMsg
};
在其它要发消息的地方,调用以下代码即可:
const WSRouter = require('./ws-router.js');
WSRouter.sendMsg('From table data');
参考资料
- Express Websocket使用
- 在express中使用websocket
最后说客户端
客户端的难点在于找到一个Angular4式语法的包,调研来去,只找到一个simple-ng-websocket,还是一个日本人写的,不情愿地用吧…
在app.module.ts中
import {SimpleNgWebSocket} from 'simple-ng-websocket';
...
providers: [....SimpleNgWebSocket....]
在业务模块中:
import {Component, OnInit} from '@angular/core';
import {SimpleNgWebSocket} from 'simple-ng-websocket';
@Component({
selector: 'app-dashboard',
templateUrl: './full-layout.component.html'
})
export class FullLayoutComponent implements OnInit {
public msgCount: any;
public ngws: SimpleNgWebSocket;
constructor() {
this.ngws = new SimpleNgWebSocket('ws://192.168.1.240:80');
this.msgCount = 0;
this.ngws.on('message', (msg) => {
this.msgCount++;
console.log('msg:');
console.log(msg);
});
}
public sendMessage(msg: string): void {
this.ngws.send(msg);
}
public disabled: boolean = false;
public status: { isopen: boolean } = {isopen: false};
public toggled(open: boolean): void {
console.log('Dropdown is now: ', open);
}
public toggleDropdown($event: MouseEvent): void {
$event.preventDefault();
$event.stopPropagation();
this.status.isopen = !this.status.isopen;
}
ngOnInit(): void {
}
}
参考资料
- node+express+socket搭建一个实时推送应用
- simple-ng-websocket
- 一步一步教你用websocket进行消息推送系列三(iOS版本)