Node.js 同时运行一个 http 服务器和 web socket 服务器

Posted

技术标签:

【中文标题】Node.js 同时运行一个 http 服务器和 web socket 服务器【英文标题】:Node.js running an http server and web socket server concurrently 【发布时间】:2018-04-22 08:44:12 【问题描述】:

我一直在尝试实现一个从特定计算机接收 POST 请求的 HTTP 服务器。然后,HTTP 服务器将提取收到的消息正文,并使用 Web 套接字将正文的数据发送到另一个客户端。

HTTP 服务器的代码如下:

    var http=require('http');


    var server = http.createServer(function(request, response)
        var msgbody='';
        if(request.method == "POST")
             request.on('data', function(data)
                  msgbody=data;

                  //upon receiving POST request send msgbody to the client using websockets
             );
        
    ).listen(80);

能否请您提供一些关于如何在运行的 HTTP 服务器旁边正确实现 Web 套接字部分的见解? HTTP 服务器和 Web 套接字服务器需要在相同的端口和 IP 地址上运行。

谢谢

【问题讨论】:

【参考方案1】:

是的,你完全可以做到。对于初学者来说,一件令人困惑的事情是 websocket 初始请求不会出现在您的 data 事件中。它将来到upgrade 事件。详情请见node docs。

在您的实例中,您的其他服务器将需要首先使用 websocket upgrade 请求联系该服务器,然后将建立该连接。然后,当您收到 POST 请求时,您需要通过来自另一台服务器的现有 websocket 请求重新发送该数据。

您最好的选择绝对是使用现有的库,例如 ws。您可以使用此库附加到现有的 http 服务器。 See example here。 (例子是 express,但如果你看我相信ws 库实际上是附加到一个常规节点 http 服务器)

如果您对它的工作原理感到好奇,或者如果您一心想编写自己的 websocket 服务器:这当然是可能的。这是一个简单的示例,说明您需要做什么才能从客户端接收数据帧。我从来没有真正开始制作发送帧,但this MDN page 详细解释了整个过程。

server.on('upgrade', handleWS);

function handleWS(request, socket, buf) 
    var key = getHeader(request, 'Sec-WebSocket-Key');
    var magic = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
    var shasum = crypto.createHash('sha1');
    shasum.update(key + magic);
    var akey = shasum.digest('base64');
    var resp = ['HTTP/1.1 101 Switching Protocols',
        'Upgrade: websocket',
        'Connection: Upgrade',
        'Sec-WebSocket-Accept: ' + akey, '', ''].join('\r\n');
    console.log(key, resp);
    socket.write(resp);
    var inbuff = '';
    socket.on('data', function (buf) 
        var fin = buf.readUInt8(0) >> 7;
        var opcode = buf.readUInt8(0) & 15; //0=cont, 1=text, 2=binary
        var mask = buf.readUInt8(1) >> 7, bmask;
        var len = buf.readUInt8(1) & 127;
        var i = 2;
        if (len === 126)  len = buf.readUInt16BE(i); i += 2; 
        else if (len === 127) 
            len = (buf.readUInt32BE(i) << 32) + buf.readUInt32BE(6);
            i += 8;
        
        if (mask)  bmask = buf.slice(i, i + 4); i += 4; 
        data = buf.slice(i, i + len);
        if (mask) for (var j = 0; j < data.length; j++) 
            data[j] = data[j] ^ bmask[j % 4];
        if (opcode === 1) data = data.toString('utf8');
        // todo: handle fragmentation
        console.log(fin, opcode, mask, len, data);
    )

function getHeader(req, key) 
    var keyl = key.toLowerCase()
    for (var k in req.headers) if (k.toLowerCase() === keyl) return req.headers[k];
    return '';

【讨论】:

以上是关于Node.js 同时运行一个 http 服务器和 web socket 服务器的主要内容,如果未能解决你的问题,请参考以下文章

为什么同时运行VSCode可以显着提高Windows服务器上的Node.js性能?

Node.JS、Express 和 Heroku - 如何处理 HTTP 和 HTTPS?

Node.js 实现第一个应用以及HTTP模块和URL模块应用

Node.js 创建第一个应用

Node.js 创建第一个应用

使用 node.js 运行许多并行 http 请求