3

我正在尝试在 nodejs 中编写一个非常简单的 websocket 服务器,但我遇到了一个问题。在浏览器上,WebSocket.onclose 函数是唯一被触发的函数(onopen、onmessage 和 onerror 不是)。我已经在 Chrome7 和 FireFox4 中进行了测试。这是我的服务器代码:

var http = 要求('http'),
    净 = 要求('净'),
 加密 = 要求('加密');

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

server.on('connection', function (stream) {
 stream.setEncoding('utf8');
 流.setTimeout(0);
 流.setNoDelay(true);
 stream.on('数据',函数(数据){
  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("****Incoming****\r\n" + data);
  var key1 = sec1_regex.exec(data)[1];
  var num1 = parseInt(key1.match(/\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 协议握手\r\n升级:WebSocket\r\n连接:升级\r\nSec-WebSocket-Origin:"
   + 来源 + "\r\nSec-WebSocket-Location: ws://127.0.0.1:8124/\r\n" +
      md5.digest('二进制');
  stream.write(响应,'二进制');
  console.log("****Outgoing****\r\n" + response);
 });
});

server.listen(8124, '127.0.0.1');

我的客户代码:

  函数连接(){
   如果(窗口。WebSocket){
    尝试 {
     ws = new WebSocket('ws://127.0.0.1:8124');
     ws.onopen = 函数 () {
      警报(“打开”);
     };
     ws.onclose = 函数() {
      警报(“关闭”);
     };
     ws.onerror = 函数(错误){
      警报(“错误!”);
     };
     ws.onmessage = 函数() {
      警报('消息');
     };
    } 抓住(前){
     警报(例如);
    }
   }
  }
 
4

2 回答 2

5

好的,这里有一些问题,只onclose触发句柄的原因是浏览器没有收到有效的握手,因此终止了连接。

  1. 您始终ws://127.0.0.1:8124/作为位置发送,该位置应与浏览器在请求中发送的任何内容完全匹配,在这种情况下它很可能是最有可能的localhost:8124,因此您应该ws://localhost:8124/在这种情况下返回。

  2. 您在\r\n响应标头之后缺少另一个,因此您实际上没有发送任何正文。

  3. 您的哈希值计算似乎有问题,我仍在尝试弄清楚是什么

对于一个工作(而且非常小)的实现,请参见这里:http:
//github.com/BonsaiDen/NodeGame-Shooter/blob/master/server/ws.js

于 2010-09-03T16:15:56.093 回答
1

您可以监听 http 服务器的升级事件。

它喜欢:

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');

//...
}
于 2012-09-20T17:27:44.363 回答