为什么WebSocket.onmessage事件不会触发?

经过几个小时的忙碌之后,我根本找不到解决办法。 我正在使用“node.js”为我正在开发的基于canvas的在线游戏的WebSocket服务器上工作。 我的游戏可以很好地连接到服务器,它接受握手,甚至可以发送消息到服务器。 但是,当服务器响应客户端时,客户端不会收到消息。 没有错误,没有什么,只是平静地坐在那里。 我已经撕开了我的代码,试图解决这个问题的一切,但唉,没有。

这是我的服务器代码的一个剥离的副本。 正如我之前所说,握手工作正常,服务器接收数据正常,但发送数据回到客户端没有。

var sys = require('sys'), net = require('net'); var server = net.createServer(function (stream) { stream.setEncoding('utf8'); var shaken = 0; stream.addListener('connect', function () { sys.puts("New connection from: "+stream.remoteAddress); }); stream.addListener('data', function (data) { if (!shaken) { sys.puts("Handshaking..."); //Send handshake: stream.write( "HTTP/1.1 101 Web Socket Protocol Handshake\r\n"+ "Upgrade: WebSocket\r\n"+ "Connection: Upgrade\r\n"+ "WebSocket-Origin: http://192.168.1.113\r\n"+ "WebSocket-Location: ws://192.168.1.71:7070/\r\n\r\n"); shaken=1; sys.puts("Handshaking complete."); } else { //Message received, respond with 'testMessage' var d = "testMessage"; var m = '\u0000' + d + '\uffff'; sys.puts("Sending '"+m+"' to client"); var result = stream.write(m, "utf8"); /* Result is equal to true, meaning that it pushed the data out. Why isn't the client seeing it?!? */ } }); stream.addListener('end', function () { sys.puts("Connection closed!"); stream.end(); }); }); server.listen(7070); sys.puts("Server Started!"); 

这是我的客户端代码。 它使用Chrome本地WebSockets。

 socket = new WebSocket("ws://192.168.1.71:7070"); socket.onopen = function(evt) { socket.send("blah"); alert("Connected!"); }; socket.onmessage = function(evt) { alert(evt.data); }; 

 var m = '\u0000' + d + '\uffff'; var result = stream.write(m, "utf8"); 

啊,这似乎不太正确。 它应该是一个零字节,后跟一个UTF-8编码的string,后跟一个0xFF字节。

\uFFFF不以UTF-8编码为0xFF字节:您得到0xC3 0xBF。 实际上没有字符会产生UTF-8编码的0xFF:这就是为什么它在WebSocket中被选为终结符。

我不熟悉node.js,但我想你会需要这样说:

 stream.write('\u0000'+d, 'utf-8'); stream.write('\xFF', 'binary'); 

或者手动UTF-8编码并以二进制forms发送。

握手也是值得怀疑的,尽pipe我猜这是一个尽可能简单的初稿,目前可能对您有用。 你依靠的是第一个数据包是整个握手头,而没有其他的东西,那么第二个数据包就是有效载荷数据。 这并不能保证。 您可能需要收集缓冲区中的data ,直到您看到0x0D 0x0A 0x0D 0x0A标记为结尾的标头,然后检查标头内容并可能返回101,然后从该标记之后的数据继续。