开发者

NodeJS WebSocket Handshake Silently Failing?

开发者 https://www.devze.com 2023-01-14 01:59 出处:网络
I\'m trying to write a very simple websocket server in nodejs, and I\'m running into an issue. On the browser, the the WebSocket.onclose function is the only one that is fired (onopen, onmessage, and

I'm trying to write a very simple websocket server in nodejs, and I'm running into an issue. On the browser, the the WebSocket.onclose function is the only one that is fired (onopen, onmessage, and onerror are not). I've tested in Chrome7 and FireFox4. Here's my server code:

var http = require('http'),
    net = require('net'),
 crypto = require('crypto');

var server = http.createServer(function (req, res) {
 console.log(req);
});

server.on('connection', function (stream) {
 stream.setEncoding('utf8');
 stream.setTimeout(0);
 stream.setNoDelay(true);
 stream.on('data', function (data) {
  var sec1_regex = /Sec-WebSocket-Key1:(.*)/g;
  var sec2_regex = /Sec-WebSocket-Key2:(.*)/g;
  var origin_regex = /Origin: (.*)/g;
  var protocol_regex = /Sec-WebSocket-Protocol: (.*)/g;

  console.log(stream);
  console.log("****Incoming****\r\n" + data);
  var key1 = sec1_regex.exec(data)[1];
  var num1 = parseInt(key1.matc开发者_StackOverflow中文版h(/\d/g).join(''))/(key1.match(/\s/g).length - 1);
  console.log("num1: " + num1);
  var key2 = sec2_regex.exec(data)[1];
  var num2 = parseInt(key2.match(/\d/g).join(''))/(key2.match(/\s/g).length - 1);
  console.log("num2: " + num2);
  var lastbytes = data.slice(-8);
  var origin = origin_regex.exec(data)[1];

  var md5 = crypto.createHash('md5');
  md5.update(String.fromCharCode(num1 >> 24 & 0xFF, num1 >> 16 & 0xFF, num1 >> 8 & 0xFF, num1 & 0xFF));
  md5.update(String.fromCharCode(num2 >> 24 & 0xFF, num2 >> 16 & 0xFF, num2 >> 8 & 0xFF, num2 & 0xFF));
  md5.update(lastbytes);
  var response = "HTTP/1.1 101 WebSocket Protocol Handshake\r\nUpgrade: WebSocket\r\nConnection: Upgrade\r\nSec-WebSocket-Origin: "
   + origin + "\r\nSec-WebSocket-Location: ws://127.0.0.1:8124/\r\n" +
      md5.digest('binary');
  stream.write(response, 'binary');
  console.log("****Outgoing****\r\n" + response);
 });
});

server.listen(8124, '127.0.0.1');

And my client code:


  function connect() {
   if (window.WebSocket) {
    try {
     ws = new WebSocket('ws://127.0.0.1:8124');
     ws.onopen = function () {
      alert("open");
     };
     ws.onclose = function() {
      alert("close");
     };
     ws.onerror = function(err) {
      alert("err!");
     };
     ws.onmessage = function() {
      alert('message');
     };
    } catch (ex) {
     alert(ex);
    }
   }
  }
 


OK there a couple of things wrong here, the reason why only the onclose handle is fired is because the browser does not receive a valid handshake and therefore terminates the connection.

  1. You always send ws://127.0.0.1:8124/ as the location, the location should exactly match whatever the browser send in the request in this case it would be most likely localhost:8124 so you should return ws://localhost:8124/ in such a case.

  2. You're missing another \r\n after the response headers, so you're in fact not sending any body.

  3. There seems to be something wrong with your calculation of the hash value, I'm still trying to figure out what though

For a working(and pretty small) implementation see here:
http://github.com/BonsaiDen/NodeGame-Shooter/blob/master/server/ws.js


You may listen the upgrade event of the http server.

it likes:

httpserver.onupgrade = function(request, socket) {
var key = request.headers['sec-websocket-key'];
key = require('crypto').createHash('sha1').update(key+"258EAFA5-E914-47DA-95CA-C5AB0DC85B11").digest('base64');

var sResponse = "HTTP/1.1 101 Switching Protocols\r\n" +
    "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" +
    "Sec-WebSocket-Accept: " + key + "\r\n\r\n";
    socket.write(sResponse,'ascii');

//...
}
0

精彩评论

暂无评论...
验证码 换一张
取 消