Почему не происходит событие WebSocket.onmessage? - PullRequest
1 голос
/ 29 апреля 2010

Поработав с этим часами, я просто не могу найти решение.Я работаю на сервере WebSocket, используя "node.js" для основанной на холсте онлайн-игры, которую я разрабатываю.Моя игра может нормально подключаться к серверу, она принимает рукопожатие и даже может отправлять сообщения на сервер.Однако, когда сервер отвечает клиенту, клиент не получает сообщение.Никаких ошибок, ничего, просто мирно сидит.Я разорвал свой код, пытаясь все, что мог придумать, чтобы это исправить, но, увы, ничего.

Вот раздетая копия кода моего сервера.Как я уже говорил, рукопожатие работает нормально, сервер получает данные нормально, но отправка данных клиенту - нет.

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

1 Ответ

4 голосов
/ 29 апреля 2010
var m = '\u0000' + d + '\uffff';
var result = stream.write(m, "utf8");

Ах, это кажется не совсем правильным. Это должен быть нулевой байт, за которым следует строка в кодировке UTF-8, за которой следует байт 0xFF.

\uFFFF не кодирует в UTF-8 байт 0xFF: вы получаете 0xC3 0xBF. Фактически, ни один символ никогда не выдаст 0xFF в кодировке UTF-8: именно поэтому он был выбран как терминатор в WebSocket.

Я не знаком с node.js, но думаю, вам нужно сказать что-то вроде:

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

Или вручную кодировать UTF-8 и отправлять в двоичном виде.

Рукопожатие также сомнительно, хотя я думаю, что это простой, насколько возможно, первый набросок, который, вероятно, работает на данный момент. Вы полагаетесь на то, что первый пакет представляет собой весь заголовок рукопожатия и больше ничего, а второй - данные полезной нагрузки. Это совсем не гарантировано. Возможно, вы захотите собрать data в буфере, пока не увидите маркер 0x0D 0x0A 0x0D 0x0A для конца заголовков, затем проверьте содержимое заголовка и, возможно, верните 101, затем продолжите данные после этого маркера.

...