如何在koa中共享http与websocket服务端口
安装 ws 模块
npm install ws
服务端
创建 ws 服务
因为您已经使用express创建了服务器,并且在express内部调用了handleUpgrade方法,
因此您需要通知WebSocket服务器忽略服务器启动部分,并继续使用现有资源,同时将选项指定为{ noServer: true }
const wss = new ws.WebSocketServer({ noServer: true }) //
wss.on('connection', function connection(ws) {
console.log('client wss 链接');
ws.on('error', (err)=>{
console.log('wss error',err);
console.error
});
ws.on('message', function message(data) {
console.log('received: %s', data);
});
ws.on("close", function (code, reason) {
console.log("关闭连接")
console.log(code, reason)
});
ws.send('something');
});
注册 upgrade 方法
让http服务处理所有的请求,在遇到Connection:Upgrade和Upgrade:websocket时换用websocket服务
根据不同路径,链接 ws 服务
server.on('upgrade', function upgrade(request, socket, head) {
const { pathname } = new URL(request.url, 'ws://127.0.0.1:3000');
if (pathname === '/foo') {
wss.handleUpgrade(request, socket, head, function done(ws) {
wss.emit('connection', ws, request);
});
} else if (pathname === '/bar') {
wss2.handleUpgrade(request, socket, head, function done(ws) {
wss2.emit('connection', ws, request);
});
} else {
socket.destroy();
}
});
完整代码
var app = require('../app');
var debug = require('debug')('demo:server');
var http = require('http');
const ws = require('ws')
/**
* Get port from environment and store in Express.
*/
var port = normalizePort(process.env.PORT || '3000');
// app.set('port', port);
/**
* Create HTTP server.
*/
var server = http.createServer(app.callback());
/**
* Listen on provided port, on all network interfaces.
*/
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
const wss = new ws.WebSocketServer({ noServer: true })
wss.on('connection', (ws)=>wsConnection(ws));
const wss2 = new ws.WebSocketServer({ noServer: true })
wss2.on('connection',(ws)=>wsConnection(ws));
function wsConnection(ws) {
console.log('client wss 链接');
ws.on('error', (err)=>{
console.log('wss error',err);
console.error
});
ws.on('message', function message(data) {
console.log('received: %s', data);
});
ws.on("close", function (code, reason) {
console.log("关闭连接")
console.log(code, reason)
});
ws.send('something');
}
server.on('upgrade', function upgrade(request, socket, head) {
const { pathname } = new URL(request.url, 'ws://127.0.0.1:3002');
if (pathname === '/api/foo') {
wss.handleUpgrade(request, socket, head, function done(ws) {
wss.emit('connection', ws, request);
});
} else if (pathname === '/bar') {
wss2.handleUpgrade(request, socket, head, function done(ws) {
wss2.emit('connection', ws, request);
});
} else {
socket.destroy();
}
});
// ....
客户端
建立 WebSocket 长链接
var ws = new WebSocket('ws://localhost:4000/')
ws.onopen = function () {
console.log('connected')
setTimeout(function () {
ws.send('hello')
}, 2000)
}
ws.onmessage = function (e) {
console.log(e.data)
}
注册 对应事件
ws.onopen
WebSocket 的连接状态readyState 变为1时调用;这意味着当前连接已经准备好发送和接受数据。这个事件处理程序通过 事件(建立连接时)触发。
ws.onopen = function () {
console.log("WebSocket is open now.");
}
ws.send
向服务端发送消息
ws.send("Hello server!");
ws.onmessage
接收到服务端消息
ws.onmessage = function (e) {
console.log(e.data)
}
ws.close
关闭长链接
ws.close("Hello server!");
完整测试代码
var ws = new WebSocket('ws://localhost:4000/')
ws.onopen = function () {
console.log('connected')
setTimeout(function () {
ws.send('hello')
}, 2000)
}
ws.onmessage = function (e) {
console.log(e.data)
}