2011-05-18 30 views
9

Con el Net Stream Object con TCP funciona muy bien (como presetend en el node.js introduction video), pero ¿cómo debo hacer esto en HTTP?Node.JS: ¿Cómo crear un servidor HTTP Chat?

¿Hay alguna manera de acceder a sockets/clients dentro de un http.createServer()? ¿O cuál es el método para hacerlo? Traté de encontrar la solución del node chat demossouce code oficial, pero realmente no lo entiendo.

Entiendo el lado del cliente js, pero ¿qué ocurre después de que (como cliente) envíe un mensaje a través de AJAX, al lado del servidor js? ¿Cómo puedo enviar a los otros clientes que están en el servidor también?

Tenga en cuenta que no quiero aprender la lógica del proceso, por lo que no quiero usar socket.io o cualquier otro marco, bibliotecas, módulos.

Muchas gracias por cualquier ayuda!

Respuesta

2

Una forma de hacerlo implica que los clientes se "suscriban" a un canal que actúa como distribuidor de mensajes. Una vez suscrito, un cliente recibe una copia de cada mensaje enviado al canal.

Muchos servicios de chat de nodos se basan en la función pubsub de redis para manejar esta distribución de mensajes de uno a cualquier número de clientes. Si quisieras "hacer tuyo", entender cómo Redis resuelve este problema sería un gran comienzo.

+1

pero la pregunta es ¿cómo se envía el mensaje al cliente?gracias por redis, esto parece interesante, sin embargo no se relaciona con 'node.js' :), pero como programador de PHP esto parece interesante – Adam

+0

Bueno, en pocas palabras, una vez que un cliente se suscribe al servicio, se crea una cola para contener cualquier mensaje enviado por otros clientes. Cuando un cliente envía un mensaje, se agrega a cada una de las colas de los otros suscriptores. Luego, el cliente solicita cualquier mensaje pendiente que se haya agregado a su propia cola. –

+2

Websockets (una función de HTML5) permite a un cliente abrir un zócalo bidireccional a un servidor web que el servidor puede usar para "enviar" mensajes al cliente. En ausencia de esta característica, los clientes sondean el servidor (a través de AJAX) por cualquier mensaje pendiente. El servidor no empuja mensajes ya que (no hay websockets) no tiene ninguna función nativa para hacerlo. Esta es la razón por la cual socket.io es tan útil. Si el cliente admite websockets, los usa. Si no, intenta una cantidad de otros medios que se reducen a largas encuestas. –

10

Lo ideal es que solo use WebSockets, pero la alternativa es ajax de largo sondeo.

Puede utilizar una técnica conocida como larga encuesta para hacer el chat. Esto significa que realiza una solicitud (ajax) al servidor y el servidor retiene esta solicitud hasta que le quedan algunos datos para enviar.

Por lo que los clientes terminan sondeando periódicamente el servidor, si el servidor no tiene nuevos mensajes, solo mantiene su solicitud. Si tiene un mensaje, lo envía de vuelta al cliente y el cliente volverá a sondear el servidor.

[[Código 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); 

Una mejor tecnología push sería Server-side events. Vea un example of it here. Esto requiere soporte del navegador (creo que Chrome y la ópera).

+1

Primero WoW, ¡muchas gracias! Esta es una forma práctica de hacerlo, pero una encuesta larga tiene problemas de rendimiento con una gran cantidad de clientes, por lo que un servidor cometa sería una buena solución, pero no sé cómo implementarlo con node.js, consulte http : //www.ape-project.org/ajax-push.html es similar a lo que quiero pero no es un nodo :) – Adam

+1

@CIRK si quiere algo similar a APE y luego instala socket.io. Si desea escribir desde cero, lea la fuente socket.io. Para el registro, no tengo ni idea de cómo implementar el servidor push en el nodo :( – Raynos

+0

No quiero APE ni socket.io: P, me gustaría saber cómo funcionan, mirando la fuente de socket.io es malo para mí: O, porque no conozco la lógica de esto: S – Adam

0

Si desea conocer los principios básicos del sondeo largo, intente consultar this article. Resumí algunas partes de mi servidor de encuestas largas, cómo las implementé y el artículo también contiene enlaces a otros recursos. Debería darte al menos una idea más completa de cuánto tiempo funcionan las encuestas.

Si desea aprender la lógica para divertirse con la codificación con node.js, y no utilizar las soluciones existentes, entonces le recomendaría ir paso a paso desde la implementación más simple y básica hasta las más complejas. . No intente construir todo desde la primera toma porque es una de las formas más seguras de fallar.