views:

410

answers:

1

Hey guys,

After toying around with this for hours, I simply cannot find a solution. I'm working on a WebSocket server using "node.js" for a canvas based online game I'm developing. My game can connect to the server just fine, it accepts the handshake and can even send messages to the server. However, when the server responds to the client, the client doesn't get the message. No errors, nothing, it just sits there peacefully. I've ripped apart my code, trying everything I could think of to fix this, but alas, nothing.

Here's a stripped copy of my server code. As I said before, the handshake works fine, the server receives data fine, but sending data back to the client does not.

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!");

Here's my client side code. It uses Chrome native 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);
};
+1  A: 
var m = '\u0000' + d + '\uffff';
var result = stream.write(m, "utf8");

Ah, that seems not quite right. It should be a zero byte, followed by a UTF-8 encoded string, followed by a 0xFF byte.

\uFFFF does not encode in UTF-8 to a 0xFF byte: you get 0xC3 0xBF. In fact no character will ever produce an 0xFF in UTF-8 encoding: that's why it was picked as a terminator in WebSocket.

I'm not familiar with node.js, but I would guess you'd need to say something like:

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

Or manually UTF-8 encode and send as binary.

The handshaking is also questionable, though I guess it's a simple-as-possible first draft that's probably working for you at the moment. You're relying on the first packet being the whole handshake header and nothing else, then the second packet being the payload data. This isn't at all guaranteed. You'll probably want to collect data in a buffer until you see the 0x0D 0x0A 0x0D 0x0A marker for the end of the headers, then check the header content and possibly return the 101, then continue from data after that marker.

bobince
Oh wow, such a simple solution! Thanks so much! I've been pulling my hair out for hours trying to solve this!As you said, the handshaking is just a temporary simple-as-possible first draft, and I'll make a better one later on.Again, thanks a million!
SumWon