使用Node.js进行WebSocket数据解析



客户端上的Websocket:

socket.send('helloworld');

Node.js:上的Websocket

socket.ondata = function(d, start, end){
     // I suppose that the start and end indicates the location of the 
     // actual data 'hello world' after the headers
     var data = d.toString('utf8', start, end);
     
     // Then I'm just printing it
     console.log(data);
});

但我在终端上收到了这个:�����]���1���/��:O

我试着理解这个医生:https://www.rfc-editor.org/rfc/rfc6455#section-5.2但这很难理解,因为我不知道应该使用什么,我的意思是,即使使用toString,我也看不到数据?

我试着用这个问题来回答和测试我如何在服务器端发送和接收WebSocket消息?但我无法让它工作,有了这个答案,我得到了一个像这样的数组[假,真,假,假,真的,真,假的]等等……我真的不知道该怎么办……:\

所以我有点困惑,在我从客户端获得数据后,我该怎么办才能获得真正的消息?

我使用的是没有任何库的原始客户端和node.js API

您正在使用哪个node.js库?根据您正在挂接的socket.ondata看起来像HTTP服务器API这一事实来判断。WebSockets不是HTTP。它有一个HTTP兼容的握手,这样WebSocket和HTTP服务就可以在同一个端口上运行,但这就是相似性的终点。握手之后,WebSockets是一种框架式全双工、长寿命的消息传输,与常规TCP套接字相比,它更类似于HTTP。

如果你想在node.js中实现你自己的WebSocket服务器,你需要直接使用套接字库(或者在现有的WebSocketserver代码上构建/借用)。

下面是一个基于Node.js的WebSocket服务器,它从WebSocket桥接到TCP套接字:https://github.com/kanaka/websockify/blob/master/other/websockify.js请注意,它是针对协议的前一个Hixie版本的(我还没有机会或动机更新它)。该协议的现代HyBI版本非常不同,但您可能能够从该实现中收集一些有用的信息。

实际上,可以从Node的HTTP API开始。这正是我在编写WebSocket Node模块时所做的https://github.com/Worlize/WebSocket-Node

如果你不想使用现有的WebSocket库(尽管你真的应该只使用现有的库),那么你需要能够解析RFC定义的二进制数据格式。它非常清楚数据的格式以及如何解释数据。从每一帧中,您必须读入所有标志,解释帧大小,可能读取遮罩关键点,并在从导线中读取内容时取消遮罩。

这就是你看不到任何可识别的东西的原因之一。。。在WebSockets中,所有客户端到服务器的通信都会被混淆,方法是使用XOR对内容应用随机掩码,以防可能毒害不了解WebSockets的旧代理服务器的缓存。

有两件事-

  1. 您正在使用哪个node.js版本?我从未见过带有start和endpt的数据事件。发出的事件只是以buffer/string作为参数的数据。

  2. 更重要的是,如果您正在挂接HTTP套接字,则应该处理HTTP数据包。它包含助听器、车身和拖车。那里可能有垃圾。

以下是本文的解决方案:

https://medium.com/hackernoon/implementing-a-websocket-server-with-node-js-d9b78ec5ffa8

parseMessage(buffer) {
    const firstByte = buffer.readUInt8(0);
    //const isFinalFrame = Boolean((firstByte >>> 7) & 0x1); 
    //const [reserved1, reserved2, reserved3] = [ Boolean((firstByte >>> 6) & 0x1), 
    Boolean((firstByte >>> 5) & 0x1), Boolean((firstByte >>> 4) & 0x1) ]; 
    const opCode = firstByte & 0xF; 
    // We can return null to signify that this is a connection termination frame 
    if (opCode === 0x8) 
        return null; 
    // We only care about text frames from this point onward 
    if (opCode !== 0x1) 
        return; 
    const secondByte = buffer.readUInt8(1); 
    const isMasked = Boolean((secondByte >>> 7) & 0x1); 
    // Keep track of our current position as we advance through the buffer 
    let currentOffset = 2; let payloadLength = secondByte & 0x7F; 
    if (payloadLength > 125) { 
        if (payloadLength === 126) { 
            payloadLength = buffer.readUInt16BE(currentOffset); 
            currentOffset += 2; 
        } else { 
            // 127 
            // If this has a value, the frame size is ridiculously huge! 
            //const leftPart = buffer.readUInt32BE(currentOffset); 
            //const rightPart = buffer.readUInt32BE(currentOffset += 4); 
            // Honestly, if the frame length requires 64 bits, you're probably doing it wrong. 
            // In Node.js you'll require the BigInt type, or a special library to handle this. 
            throw new Error('Large payloads not currently implemented'); 
        } 
    }
    const data = Buffer.alloc(payloadLength);
    // Only unmask the data if the masking bit was set to 1
    if (isMasked) {
        let maskingKey = buffer.readUInt32BE(currentOffset);
        currentOffset += 4;
        // Loop through the source buffer one byte at a time, keeping track of which
        // byte in the masking key to use in the next XOR calculation
        for (let i = 0, j = 0; i < payloadLength; ++i, j = i % 4) {
            // Extract the correct byte mask from the masking key
            const shift = j == 3 ? 0 : (3 - j) << 3; 
            
            const mask = (shift == 0 ? maskingKey : (maskingKey >>> shift)) & 0xFF;
            // Read a byte from the source buffer 
            const source = buffer.readUInt8(currentOffset++); 
            // XOR the source byte and write the result to the data 
            data.writeUInt8(mask ^ source, i); 
        }
    } else {
        // Not masked - we can just read the data as-is
        buffer.copy(data, 0, currentOffset++);
    }
    return data 
}

相关内容

  • 没有找到相关文章

最新更新