我的设置与此类似:
var WebSocketServer = require("ws").Server,
express = require("express"),
http = require("http"),
app = express(),
server = http.createServer(app);
app.post("/login", login);
app.get("/...", callSomething);
// ...
server.listen(8000);
var wss = new WebSocketServer({server: server});
wss.on("connection", function(ws){
// ...
});
我想将WebSocketServer置于特定路径下,例如"...com/whatever"
。问题是如何设置路径?有可能吗?
答案 0 :(得分:34)
答案 1 :(得分:20)
使用express-ws: https://www.npmjs.com/package/express-ws
<强>安装:强>
npm i express-ws -S
HTTP服务器示例:
const express = require('express')
const enableWs = require('express-ws')
const app = express()
enableWs(app)
app.ws('/echo', (ws, req) => {
ws.on('message', msg => {
ws.send(msg)
})
ws.on('close', () => {
console.log('WebSocket was closed')
})
})
app.listen(80)
HTTPS服务器示例:
注意我强烈建议使用NodeJS和Internet之间的中间服务器(例如Nginx)来实现HTTPS,压缩和缓存等功能,它的工作效率更高,其配置更容易更改未来
const https = require('https')
const fs = require('fs')
const express = require('express')
const expressWs = require('express-ws')
const serverOptions = {
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem')
}
const app = express()
const server = https.createServer(serverOptions, app)
expressWs(app, server)
app.ws('/echo', (ws, req) => {
ws.on('message', msg => {
ws.send(msg)
})
ws.on('close', () => {
console.log('WebSocket was closed')
})
})
server.listen(443)
浏览器客户端示例:
// wss: protocol is equivalent of https:
// ws: protocol is equivalent of http:
// You ALWAYS need to provide absolute address
// I mean, you can't just use relative path like /echo
const socketProtocol = (window.location.protocol === 'https:' ? 'wss:' : 'ws:')
const echoSocketUrl = socketProtocol + '//' + window.location.hostname + '/echo/'
const socket = new WebSocket(echoSocketUrl);
socket.onopen = () => {
socket.send('Here\'s some text that the server is urgently awaiting!');
}
socket.onmessage = e => {
console.log('Message from server:', event.data)
}
答案 2 :(得分:13)
接受的答案不再有效,并会抛出Frame Header Invalid
错误。 Pull Request #885。
当Lpinca将其删除时,
这里的问题是每个WebSocketServer都会添加一个新的监听器 HTTP服务器上的升级事件以及何时发出该事件 在所有服务器上调用handleUpgrade。
以下是解决方法:
const wss1 = new WebSocket.Server({ noServer: true });
const wss2 = new WebSocket.Server({ noServer: true });
const server = http.createServer();
server.on('upgrade', (request, socket, head) => {
const pathname = url.parse(request.url).pathname;
if (pathname === '/foo') {
wss1.handleUpgrade(request, socket, head, (ws) => {
wss1.emit('connection', ws);
});
} else if (pathname === '/bar') {
wss2.handleUpgrade(request, socket, head, (ws) => {
wss2.emit('connection', ws);
});
} else {
socket.destroy();
}
});
答案 3 :(得分:3)
您可以通过将传入的套接字请求作为中间件来使用这个简单的想法,我发现它非常有用
在您的app.js中
const server = http.createServer(app)
const WebSocket = require('ws');
const ws = new WebSocket.Server({server});
现在将中间件放在这里
app.use(function (req, res, next) {
req.ws = ws;
return next();
});
或者,显然更简单一些:
app.ws=ws;
现在您的ws构造在路由器中可用,例如:
// main user dashboard GET
router.get('/', async function(req, res) {
let ws = req.ws
ws.once('connection', function connection(wss) {
wss.on('message', function incoming(message) {
console.log('received: %s', message);
});
wss.send(JSON.stringify('it works! Yeeee! :))' ));
});
});
或者如果您通过app.ws将其附加到您的应用程序中:
// main user dashboard GET
router.get('/', async function(req, res) {
req.app.ws.once('connection', (wss) => {
console.log('connected:', req.app.ws.clients.size)
});
});
非常注意使用“ ws.once”而不是“ ws.on”,否则您将在每个请求的websocket.server的新实例上获得多个连接。
干杯! :)
答案 4 :(得分:3)
要基于Ivan Kolyhalov的方法,可以通过将WebSocketServer(或其任何属性)分配给app.locals
来从任何端点访问WebSocketServer。因此,您只需要在server.js
中管理到WebSocketServer的处理连接。
在下面的代码中,我们将WebSocketServer的clients
属性分配给app.locals
,这使我们能够通过向路由端点发出HTTP请求,向所有连接的客户端广播/推送自定义消息。
server.js
const { createServer } = require("http");
const express = require("express");
const WebSocket = require("ws");
const app = express();
app.use(express.json({ extended: false }));
app.use("/api/pets", require("./routes/api/pets"));
const port = process.env.PORT || 5000;
const server = createServer(app);
server.listen(port, () => console.info(`Server running on port: ${port}`));
const webSocketServer = new WebSocket.Server({ server });
webSocketServer.on("connection", (webSocket) => {
console.info("Total connected clients:", webSocketServer.clients.size);
app.locals.clients = webSocketServer.clients;
});
./ routes / api / pets.js
const router = require("express").Router();
const WebSocket = require("ws");
const broadcast = (clients, message) => {
clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.send(message);
}
});
};
router.get("/dog", (req, res) => {
broadcast(req.app.locals.clients, "Bark!");
return res.sendStatus(200);
});
router.get("/cat", (req, res) => {
broadcast(req.app.locals.clients, "Meow!");
return res.sendStatus(200);
});
module.exports = router;