你如何处理基本的Websocket框架

时间:2013-01-25 03:00:34

标签: node.js websocket

我正在编写自己的web套接字实现,而不是socket.io等。

我握手很好但是当客户端发送到服务器时我无法弄清楚如何将这些数据变成有用的东西。它是一个对象吗?它是一个字符串? Docs说它是V8堆之外的一组原始内存位置。 ...?

enter image description here

功能示例(客户端是硬编码字符串)

var http = require("http");
var crypto = require("crypto");
var server = http.createServer();
server.on("upgrade", function (req, socket, upgradeHead) {
    var crypto = require("crypto");
    var shasum = crypto.createHash("sha1");
    shasum.update(req.headers["sec-websocket-key"]);
    shasum.update("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
    var hash = shasum.digest("hex");
    var myVal = new Buffer(hash, "hex").toString('base64');

    var head = "";
    head += "HTTP/1.1 101 Switching Protocols\r\n";
    head += "Connection: Upgrade\r\n";
    head += "Upgrade: WebSocket\r\n";
    head += "Sec-WebSocket-Accept: " + myVal + "\r\n\r\n";

    socket.setEncoding("utf8");
    socket.write(head);

    socket.ondata = function (data, start, end) {
        var data = data.toString("utf8", start, end);
        console.log(" start: " + start + "\n end: " + end + "\n data: " + data);
    };
});
server.on("request", function (req, res) {
    if (req.url === "/e")
        process.exit();
    if (req.url.indexOf("favicon") !== -1)
        return;

    var html = "\
                <!DOCTYPE html>\r\n\
                <html>\r\n\
                    <head>\r\n\
                        <script>\r\n\
                            var connection = new WebSocket('ws:localhost:80');\r\n\
                            connection.onopen = function () {\r\n\
                                console.log('OPEN SUCCESS');\r\n\
                                connection.send('I am a message from the client.');\r\n\
                            };\
                            connection.onmessage = function(msg) {\r\n\
                                console.log(msg);\r\n\
                            }\r\n\
                            connection.onerror = function (e) { console.log('ERROR'); console.log(e); };\r\n\
                            connection.onclose = function (e) { console.log('CLOSE'); console.log(e);};\r\n\
                        </script>\r\n\
                    </head>\r\n\
                </html>";
    res.writeHead(200, { "Content-Type": "text/html" });
    res.write(html);
    res.end();
});
server.listen(80);

node docs - socket.on(data, myFunc);

node docs - Buffer object

Tutorial I am using

Detailed WebSocket Documentation

eazy-peezy wikipedia handshake explanation

1 个答案:

答案 0 :(得分:10)

主要问题是自编写该教程以来,WebSocket协议已经发展了很多。如果您阅读了链接的规范,则5.2节将讨论数据框架。

http://tools.ietf.org/html/rfc6455#page-28

使您的数据乱码的主要问题是数据在发送时会自动屏蔽,因此您需要处理该帧。

以下是解码示例代码的示例。您需要将其展开以覆盖更大的长度,并处理规范的其他部分。

socket.ondata = function (data, start, end) {
  var message = data.slice(start, end);
  var FIN = (message[0] & 0x80);
  var RSV1 = (message[0] & 0x40);
  var RSV2 = (message[0] & 0x20);
  var RSV3 = (message[0] & 0x10);
  var Opcode = message[0] & 0x0F;
  var mask = (message[1] & 0x80);
  var length = (message[1] & 0x7F);

  var nextByte = 2;
  if (length === 126) {
    // length = next 2 bytes
    nextByte += 2;
  } else if (length === 127){
    // length = next 8 bytes
    nextByte += 8;
  }

  var maskingKey = null;
  if (mask){
    maskingKey = message.slice(nextByte, nextByte + 4);
    nextByte += 4;
  }

  var payload = message.slice(nextByte, nextByte + length);

  if (maskingKey){
    for (var i = 0; i < payload.length; i++){
      payload[i] = payload[i] ^ maskingKey[i % 4];
    }
  }

  console.log(payload.toString());
};