我正在一个需要节点服务器处理安全websocket连接的项目中。一个要求是每个websocket都是它自己的Node进程。
我的原型代码全都在一个过程中,它使我可以手动将原始套接字升级到SSL和WebSocket。这似乎有效。我以这种方式对其进行了原型设计,以便可以在创建原始套接字与应用SSL和WebSocket包装器之间插入spawn()函数。
(server.js)
#!/usr/bin/env node
'use strict';
const net = require('net');
const tls = require('tls');
const fs = require('fs');
const https = require('https');
var WebSocketServer = require('ws').Server;
const port = 3014;
const options = {
key: fs.readFileSync('certs/server/server.key'),
cert: fs.readFileSync('certs/server/server.crt'),
ca: fs.readFileSync('certs/ca/ca.crt'),
requestCert: false,
rejectUnauthorized: false
};
const wss = new WebSocketServer({
noServer: true
});
var httpsServer = https.createServer( options, (req,res) => {
console.log("https");
})
.on('connection', function(socket) {
console.log('connection https'); })
.on('upgrade', function(req,sock,head) {
console.log('upgrade https');
wss.handleUpgrade(req, sock, head, (client) => {
console.log("wss upgraded");
});
})
.on('request', function(req,res) {
console.log('request https');
})
.on('clientError',function(ex,sock) {
console.log('cliError https'); console.dir(ex);
});
var server = net.createServer((socket) => {
console.log("net_createServer()");
})
.on('connection', function(socket)
{
console.log('insecure connection');
httpsServer.emit('connection',socket);
})
.listen(port, function() {
console.log('server listening on port ' + port + '\n');
});
这是控制台输出,显示了正在触发的事件。通过原始套接字创建的httpsServer看来,它已经一路成功升级到安全Web套接字。
server listening on port 3014
net_createServer()
insecure connection
connection https
upgrade https
wss upgraded
现在,如果我将此代码分成两个程序并插入spawn(),send(),process.on.message代码,则在触发httpsServer对象上的连接事件后,它将挂起。
(parent.js)
#!/usr/bin/env node
'use strict';
const net = require('net');
const cp = require('child_process');
const port = 3014;
var server = net.createServer((socket) => {
console.log("net_createServer()");
})
.on('connection', function(socket)
{
console.log('insecure connection');
var child = cp.spawn('node', ['./child.js'], {detached: true, stdio: [0,1,2,'ipc']});
child.send("socket",socket);
child.disconnect();
child.unref();
})
.listen(port, function() {
console.log('server listening on port ' + port + '\n');
});
(child.js)
#!/usr/bin/env node
'use strict';
const tls = require('tls');
const fs = require('fs');
const https = require('https');
var WebSocketServer = require('ws').Server;
const options = {
key: fs.readFileSync('certs/server/server.key'),
cert: fs.readFileSync('certs/server/server.crt'),
ca: fs.readFileSync('certs/ca/ca.crt'),
requestCert: false,
rejectUnauthorized: false
};
const wss = new WebSocketServer({
noServer: true
});
var httpsServer = https.createServer( options, (req,res) => {
console.log("https");
})
.on('connection', function(socket) {
console.log('connection https');
})
.on('upgrade', function(req,sock,head) {
console.log('upgrade https');
wss.handleUpgrade(req, sock, head, (client) => {
console.log("wss upgraded");
});
})
.on('request', function(req,res) {
console.log('request https');
})
.on('clientError', function(ex,sock) {
console.log('cliError https');
console.dir(ex);
});
process.on('message', (msg,socket) => {
console.log("received message, msg=" + msg);
httpsServer.emit('connection',socket);
});
这是这套程序的控制台输出...
server listening on port 3014
net_createServer()
insecure connection
received message, msg=socket
connection https
如您所见,child.js程序在获取带有套接字的消息并尝试将该套接字发送到httpsServer之后挂起。 httpsServer会触发“连接”,但永远不会触发“升级”事件。如果我让它坐在那里足够长的时间,则httpsServer会触发具有以下内容的“ clientError”事件...
cliError https
Error: TLS handshake timeout
at TLSSocket._handleTimeout (_tls_wrap.js:592:22)
at Object.onceWrapper (events.js:313:30)
at emitNone (events.js:106:13)
at TLSSocket.emit (events.js:208:7)
at TLSSocket.Socket._onTimeout (net.js:410:8)
at ontimeout (timers.js:498:11)
at tryOnTimeout (timers.js:323:5)
at Timer.listOnTimeout (timers.js:290:5)
我似乎无法弄清楚为什么它作为单个进程起作用,但是在父进程和子进程之间划分代码却无法协商SSL连接。我猜我的代码在某种程度上是错误的,但是我没有看到它。