zoukankan      html  css  js  c++  java
  • nodejs服务端websocket协议

    const http = require('http');
    var crypto = require("crypto");
    var util = require("util");
    const server = http.createServer((req, res) => {
      console.log(req, res);
    }).listen(8080);
    
    server.on('upgrade', function(req, socket, upgradeHead) {
        console.log('aaaaaaaaaaa', upgradeHead.toString());
        var key = req.headers['sec-websocket-key'];
        key = crypto.createHash("sha1").update(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").digest("base64");
        var headers = [
            'HTTP/1.1 101 Switching Protocols',
            'Upgrade: websocket',
            'Connection: Upgrade',
            'Sec-WebSocket-Accept: ' + key
        ];
        socket.setNoDelay(true);
        socket.write(headers.join("
    ") + "
    
    ", 'ascii');
    
    
        socket.on('data', function(data) {
            console.log(data);
            dataHandle(data);
        });
    
        socket.on('close', function(e) {
    
        });
    
        socket.on('error', function(e) {
    
        });
    });
    
    
    function handleDataStat(data) {
        var dataIndex = 2; //数据索引,因为第一个字节和第二个字节肯定不为数据,所以初始值为2
        var secondByte = data[1]; //代表masked位和可能是payloadLength位的第二个字节
        var hasMask = secondByte >= 128; //如果大于或等于128,说明masked位为1
        secondByte -= hasMask ? 128 : 0; //如果有掩码,需要将掩码那一位去掉
    
        var dataLength, maskedData;
    
        //如果为126,则后面16位长的数据为数据长度,如果为127,则后面64位长的数据为数据长度
        if (secondByte == 126) {
          dataIndex += 2;
          dataLength = data.readUInt16BE(2);
        } else if (secondByte == 127) {
          dataIndex += 8;
          dataLength = data.readUInt32BE(2) + data.readUInt32BE(6);
        } else {
          dataLength = secondByte;
        }
    
        //如果有掩码,则获取32位的二进制masking key,同时更新index
        if (hasMask) {
          maskedData = data.slice(dataIndex, dataIndex + 4);
          dataIndex += 4;
        }
    
        //计算到此处时,dataIndex为数据位的起始位置,dataLength为数据长度,maskedData为二进制的解密数据
        return {
            index: dataIndex,
            totalLength: dataLength,
            length: dataLength,
            maskedData: maskedData,
            opcode: parseInt(data[0].toString(16).split("")[1], 16) //获取第一个字节的opcode位
        };
    }
    
    function dataHandle(data) {
        var stat = handleDataStat(data);
        var datas = [];
    console.log(stat);
        //如果opcode为9,则发送pong响应,如果opcode为10则置pingtimes为0
      if (stat.opcode === 9 || stat.opcode === 10) return;
    
      var result;
      if (stat.maskedData) {
        result = new Buffer(data.length - stat.index);
        for (var i = stat.index, j = 0; i < data.length; i++, j++) {
          //对每个字节进行异或运算,masked是4个字节,所以%4,借此循环
          result[j] = data[i] ^ stat.maskedData[j % 4];
        }
      } else {
        result = data.slice(stat.index, data.length);
      }
    
      datas.push(result);
    
      stat.length -= (data.length - stat.index);
    
    var buf = Buffer.concat(datas, stat.totalLength);
    console.log("sss:", buf.toString());
    
    console.log("sss:", stat.length);
    
      //当长度为0,说明当前帧为最后帧
      if (stat.length == 0) {
        var buf = Buffer.concat(datas, stat.totalLength);
      }
    }
    

      

  • 相关阅读:
    Python并发编程:协程-greenlet模块
    Python并发编程:协程介绍
    Python并发编程:多线程-进程池与线程池
    Python并发编程:多线程-线程queue
    程序员能力矩阵(好到这个好有压力...)
    如何让搜索引擎抓取AJAX内容? 转
    使用ReSharper打造团队代码检查流程
    JQuery Easy Ui dataGrid 数据表格 -->转
    TCP/IP协议(1):各层协议帧格式
    VC调试小结
  • 原文地址:https://www.cnblogs.com/zhanghuizong/p/8134863.html
Copyright © 2011-2022 走看看