Node.js同时运行http服务器和Web套接字服务器

时间:2018-04-22 08:44:12

标签: node.js http post websocket server

我一直在尝试实现从特定计算机接收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 个答案:

答案 0 :(得分:1)

是的,你完全可以做到这一点。对于初学者来说,一个令人困惑的事情是websocket初始请求不会进入你的data事件。它将进入upgrade事件。有关详细信息,请参阅node docs

在您的实例中,您的其他服务器需要首先使用websocket upgrade请求联系此服务器,并且将建立该连接。然后,当您收到POST请求时,您需要在已经存在的来自其他服务器的websocket请求中重新发送该数据。

您最好的选择是使用现有的库,例如ws。您可以使用此库附加到现有的http服务器。 See example here。 (示例说明了,但如果你看,我相信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 '';
}