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("\r\n") + "\r\n\r\n", '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);
  }
}

  

posted @ 2017-12-28 11:37  有我在  阅读(846)  评论(0编辑  收藏  举报