你如何处理一个基本的 Websocket 框架 [英] How do you process a basic Websocket frame

查看:22
本文介绍了你如何处理一个基本的 Websocket 框架的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我有一个很好的握手,但是当客户端发送到服务器时,我不知道如何将这些数据转换成任何有用的东西.它是一个对象吗?是字符串吗?文档说它是 V8 堆之外的原始内存位置数组....?

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

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 交换协议\r\n";head += "连接:升级\r\n";head += "升级:WebSocket\r\n";head += "Sec-WebSocket-Accept:" + myVal + "\r\n\r\n";socket.setEncoding("utf8");套接字.写(头);socket.ondata = 函数(数据,开始,结束){var data = data.toString("utf8", start, end);console.log(" 开始:" + 开始 + "\n 结束:" + 结束 + "\n 数据:" + 数据);};});server.on(请求",函数(req,res){if (req.url === "/e")process.exit();if (req.url.indexOf("favicon") !== -1)返回;var html = "\<!DOCTYPE html>\r\n\\r\n\<头部>\r\n\<脚本>\r\n\var connection = new WebSocket('ws:localhost:80');\r\n\connection.onopen = function () {\r\n\console.log('打开成功');\r\n\connection.send('我是来自客户端的消息.');\r\n\};\connection.onmessage = function(msg) {\r\n\console.log(msg);\r\n\}\r\n\connection.onerror = function (e) { console.log('ERROR');控制台日志(e);};\r\n\connection.onclose = function (e) { console.log('CLOSE');console.log(e);};\r\n\</脚本>\r\n\</头>\r\n\</html>";res.writeHead(200, { "Content-Type": "text/html" });res.write(html);重发();});服务器.听(80);

节点文档 - socket.on(data, myFunc);

节点文档 - 缓冲区对象

我正在使用的教程

详细的 WebSocket 文档

eazy-peezy 维基百科握手解释

解决方案

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

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

导致你的数据乱码的主要问题是数据在发送时会自动屏蔽,所以你需要对帧进行处理.

这是一个解码示例代码的示例.您需要扩展它以涵盖更大的长度,并处理规范的其他部分.

socket.ondata = 函数(数据,开始,结束){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 操作码 = 消息 [0] &0x0F;var mask = (message[1] & 0x80);var length = (message[1] & 0x7F);var nextByte = 2;如果(长度 === 126){//长度 = 接下来的 2 个字节nextByte += 2;} else if (长度 === 127){//长度 = 接下来的 8 个字节nextByte += 8;}var maskingKey = null;如果(掩码){maskingKey = message.slice(nextByte, nextByte + 4);nextByte += 4;}var payload = message.slice(nextByte, nextByte + length);如果(掩码键){for (var i = 0; i 

I am writing my own implementation for web sockets instead of socket.io and the like.

I have a good handshake but when the client sends to the server I can't figure out how to turn that data into anything useful. Is it an object? Is it a string? Docs say it is an array of raw memory locations outside the V8 heap. ...?

FUNCTIONING EXAMPLE (client is hard coded string)

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

解决方案

The main issue is that the WebSocket protocol has evolved a lot since that tutorial was written. If you read the spec that you linked to, section 5.2 talks about the data framing.

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

The main issue that makes your data gibberish is that the data is automatically masked when sent, so you need to process the frame.

Here's an example to decode your sample code. You will need to expand it to cover larger lengths, and handle other parts of the spec.

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());
};

这篇关于你如何处理一个基本的 Websocket 框架的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆