2011-05-18 13 views
9

Z obiektem Net Stream z TCP działa świetnie (jako presetend w node.js introduction video), ale jak mam to zrobić w HTTP?Node.JS: Jak utworzyć serwer czatu HTTP?

Czy istnieje sposób dostępu do gniazd/klientów w ramach http.createServer()? Albo jak to zrobić? Próbowałem znaleźć rozwiązanie od urzędnika node chat demossouce code, ale nie rozumiem.

Rozumiem stronę js klienta, ale co się dzieje po tym, jak ja (jako klient) wysyłam wiadomość przez AJAX, po stronie serwera js? Jak mogę wysłać do innych klientów, którzy również są na serwerze?

Należy pamiętać, że nie powinienem uczyć się logiki procesu, więc nie chcę używać socket.io ani żadnych innych frameworków, bibliotek, modułów.

Dziękuję bardzo za pomoc!

Odpowiedz

2

Jednym ze sposobów na to, że klienci subskrybują kanał, który działa jako dystrybutor wiadomości. Po subskrypcji klient otrzymuje kopię każdej wiadomości wysłanej na kanał.

Wiele usług czatów węzłowych polega na funkcji pubsub redis, która obsługuje tę dystrybucję wiadomości od jednej do dowolnej liczby klientów. Jeśli chcesz "przeturlać się", zrozumienie, jak Redis rozwiązuje ten problem, byłoby świetnym początkiem.

+1

, ale pytanie brzmi, w jaki sposób wiadomość jest wysyłana do klienta?dziękuję za redis, wygląda to interesująco, ale nie odnosi się do 'node.js' :), ale jako programista PHP wygląda to interesująco – Adam

+0

Po prostu, jeśli klient zasubskrybuje usługę, tworzona jest kolejka do przechowywania wszelkie wiadomości wysłane przez innych klientów. Gdy klient wysyła wiadomość, jest dodawany do każdej kolejki pozostałych subskrybentów. Następnie klient żąda wiadomości oczekujących, które zostały dodane do własnej kolejki. –

+2

Websockets (funkcja HTML5) pozwala klientowi otworzyć dwukierunkowe gniazdo do serwera WWW, którego serwer może użyć do "wypychania" wiadomości do klienta. W przypadku braku tej funkcji klienci odpytują serwer (za pośrednictwem AJAX) o wszelkie oczekujące wiadomości. Serwer nie przesyła wiadomości (ponieważ nie ma w nich sieci web), ale nie ma natywnej możliwości. Właśnie dlatego socket.io jest tak przydatny. Jeśli klient obsługuje strony internetowe, używa ich. Jeśli nie, próbuje wielu innych środków, które powracają do długiego głosowania. –

10

Najlepiej użyć po prostu WebSockets, ale alternatywą jest długotrwałe sondowanie ajax.

Do wykonania czatu można użyć techniki zwanej długim sondowaniem. Oznacza to, że wysyłasz zapytanie (ajax) do serwera, a serwer przechowuje to żądanie, dopóki nie pozostawi pewnych danych do wysłania.

Tak więc klienci kończą cyklicznie odpytywanie serwera, jeśli serwer nie ma nowych wiadomości, po prostu wstrzymuje żądanie. Jeśli ma wiadomość, wysyła ją z powrotem do klienta, a klient ponownie odpytuje serwer.

[[Kod Pseudo]]

// Client.js

var Socket = function(ip, port, name) { 
    this.ip = ip; 
    this.port = port; 
    this.name = name; 
    this._cbs = []; 
    this._poll(); 
}; 

// Call the server periodically for data. 
Socket.prototype._poll = function() { 
    var that = this; 
    // if the server does not return then call it again 
    var timer = setTimeout(function() { 
     this._poll(); 
    }, 5000); 
    $.ajax({ 
     type: "GET", 
     timeout: 5000, 
     data: { 
      name: this.name 
     }, 
     url: this.ip + ":" + this.port, 
     success: function(data) { 
      // server returned, kill the timer. 
      clearTimeout(timer); 
      // send the message to the callback. 
      for (var i = 0; i < that._cbs.length; i++) { 
       that._cbs[i](data); 
      } 
      // call the server again 
      that._poll(); 
     } 
    }); 
}; 

// Add a callback for a message event 
Socket.prototype.on = function(event, cb) { 
    if (event === "message") { 
     this._cbs.push(cb); 
    } 
}; 

// Send a message to the server 
Socket.prototype.send = function(message) { 
    $.ajax({ 
     data: { 
       message: message, 
       name: this.name 
     }, 
     type: "GET", 
     url: this.ip + ":" + this.port 
    }); 
}; 

var socket = new Socket('192.168.1.1', '8081', "Raynos"); 
socket.on("message", function(data) { 
    console.log(data); 
}); 
socket.send("Hello world!"); 

// server.js

var url = require("url"); 
var events = require("events"); 
// store messages for clients 
var clients = {}; 

var emitter = new events.EventEmitter(); 

http.createServer(function(req, res) { 
    // get query string data 
    var data = url.parse(req.url, true).query; 
    // if client is not initialized then initialize it. 
    if (data.name && !clients[data.name]) { 
     clients[data.name] = []; 
    } 
    // if you posted a message then add it to all arrays 
    if (data.message) { 
     for (var k in clients) { 
       clients[k].push(data.name + " : " + data.message); 
     } 
     // tell long pollers to flush new data. 
     emitter.emit("new-data"); 
    } else if (clients[data.name].length > 0) { 
     // else empty the clients array down the stream 
     for (var i = 0; i < clients[data.name].length; i++) { 
       res.write(clients[data.name].shift()); 
     }; 
     res.end(); 
    // long polling magic. 
    } else { 
     var cb = function() { 
       for (var i = 0; i < clients[data.name].length; i++) { 
        res.write(clients[data.name].shift()); 
       }; 
       res.end(); 
       // kill that timer for the response timing out. 
       clearTimeout(timer); 
     } 
     // when we get data flush it to client 
     emitter.once("new-data", cb); 
     var timer = setTimeout(function() { 
       // too long has passed so remove listener and end response. 
       emitter.removeListener(cb); 
       res.end(); 
     }, 4500); 
    } 
}).listen(8081); 

Lepsza technologia Push byłoby Server-side events. Zobacz example of it here. Nie wymaga to jednak obsługi przeglądarki (wydaje mi się, że to Chrome i opera).

+1

Najpierw WoW, bardzo dziękuję! Jest to działający sposób na to, ale długie polling ma problemy z wydajnością z ogromną liczbą klientów, więc serwer komet byłby dobrym rozwiązaniem, ale nie wiem jak zaimplementować go z node.js, spójrz na http : //www.ape-project.org/ajax-push.html jest podobny do tego, co chcę, ale nie jest węzłem :) – Adam

+1

@CIRK jeśli chcesz coś podobnego do APE, to zainstaluj socket.io. Jeśli chcesz napisać od początku, przeczytaj źródło socket.io. Dla zapisu nie mam pojęcia jak zaimplementować push serwera w węźle :( – Raynos

+0

Nie chcę APE ani socket.io: P, chciałbym wiedzieć, jak one działają, patrząc na źródło socket.io jest złe dla mnie: O, ponieważ nie znam logiki tego: S – Adam

0

Jeśli chcesz poznać podstawowe zasady długiego sondowania, spróbuj spojrzeć na this article. Podsumowałem tam niektóre części mojego długiego serwera ankiety, jak je zaimplementowałem, a artykuł zawiera także linki do innych zasobów. Powinien dać ci przynajmniej większy obraz tego, jak długo trwa polling.

Jeśli chcesz nauczyć się logiki, aby mieć trochę zabawy z kodowaniem przy użyciu node.js i nie używać istniejących rozwiązań, to polecam krok po kroku od najprostszej i podstawowej implementacji do bardziej skomplikowanych rzeczy . Nie próbuj budować całej rzeczy od pierwszego strzału, ponieważ jest to jeden z najpewniejszych sposobów na porażkę.