Un chat es una comunicación de uno a muchos, mientras que cada uno de los muchos puede enviar mensajes y recibirá mensajes de todos los demás.
Estas dos acciones (envío, recepción) ocurren continuamente. Así que esto parece un ciclo sin fin, mientras que el usuario puede ingresar (unirse al chat) y salir (abandonar el chat).
- entrar
- enviar mensaje
- recibir el mensaje
- salida
Así que el bucle se parece a esto (pseudo-código) en el lado del cliente:
while (userInChat)
{
if (userEnteredMessages)
{
userSendMessages(userEnteredMessages)
}
if (chatNewMessages)
{
displayMessages(chatNewMessages)
}
}
Como ya nota en su pregunta, el problema es implementar tal tipo de chat para un sitio web.
Para implementar dicho "bucle" para un sitio web, ante todo se enfrenta a la situación de que no desea tener un bucle real aquí. Mientras el usuario esté en el chat, se ejecutará, se ejecutará y se ejecutará. Entonces, quiere distribuir la ejecución del ciclo a lo largo del tiempo.
Para ello, se puede convertir en una colección de funciones de eventos:
ChatClient
{
function onEnter()
{
}
function onUserInput(messages)
{
sendMessages = send(messages)
display(sendMessages)
}
function onReceive(messages)
{
display(messages)
}
function onExit()
{
}
}
Ahora es posible activar eventos en lugar de tener un bucle. Solo queda la implementación para desencadenar estos eventos a lo largo del tiempo, pero por el momento esto no es realmente interesante porque dependería de cómo se implementa realmente el intercambio de datos de chat.
Siempre hay un punto remoto donde un cliente de chat está (de alguna manera) conectado para enviar sus propios mensajes y recibir nuevos mensajes de.
Esto es una especie de transmisión de mensajes de chat. De nuevo, esto parece un bucle, pero de hecho es una secuencia. Al igual que en el bucle de clientes de chat, en algún momento se engancha a la transmisión y enviará entrada (escritura) y recibirá salida (lectura) de esa transmisión.
Esto ya es visible en el pseudocódigo ChatClient anterior, hay un evento cuando el usuario ingresa uno o varios mensajes que luego serán enviados (escritos). Y los mensajes de lectura estarán disponibles en la función de evento onReceive.
Como la transmisión de datos está en orden, es necesario que haya orden. Como todo esto está basado en eventos y hay varios clientes disponibles, esto requiere un manejo dedicado. Como el orden es relativo, solo funcionará en su contexto. El contexto podría ser el momento (un mensaje llegó antes de otro mensaje), pero si el cliente de chat tiene otro reloj como el servidor u otro cliente, no podemos usar el reloj existente como fuente de tiempo para el orden de los mensajes, ya que normalmente difiere entre computadoras en una WAN.
En su lugar, puede crear su propio tiempo para alinear todos los mensajes. Con un tiempo compartido en todos los clientes y servidores, se puede implementar una secuencia ordenada. Esto se puede hacer fácilmente simplemente numerando los mensajes en un lugar central. Afortunadamente, su chat tiene un lugar central, el servidor.
La secuencia de mensajes comienza con el primer mensaje y finaliza con el último. Entonces, lo que simplemente debe hacer es dar el primer mensaje al número 1 y luego cada nuevo mensaje obtendrá el siguiente número más alto. Vamos a llamarlo ID del mensaje.
Por lo tanto, independientemente de la tecnología de servidor que vaya a utilizar, el chat sabe qué tipo de mensajes: mensajes con una ID y mensajes sin ID.Esto también representa el estado de un mensaje: ya sea no parte o parte de la transmisión.
Los mensajes asociados a la transmisión no son los que el usuario ya ha ingresado pero que aún no se han enviado al servidor. Mientras que el servidor recibe los mensajes de "libres", puede ponerlos en la corriente mediante la asignación de la ID:
function onUserInput(messages)
{
sendMessages = send(messages)
display(sendMessages)
}
Como este ejemplo muestra pseudo código, esto es lo que está pasando aquí. El evento onUserInput recibe mensajes que aún no forman parte de la transmisión. La rutina sendMessages devolverá su representación transmitida, que luego se mostrará.
La rutina de visualización luego puede mostrar los mensajes en su orden de transmisión.
Por lo tanto, independientemente de cómo se implemente la comunicación entre el cliente y el servidor, con esa estructura, puede manejar un sistema de chat basado en mensajes y desvincularlo de las tecnologías subyacentes.
Lo único que debe hacer el servidor es tomar los mensajes, dar a cada mensaje una ID y devolver estos ID. La asignación de la ID normalmente se hace cuando el servidor almacena los mensajes en su base de datos. Una buena base de datos se ocupa de numerar correctamente los mensajes, por lo que no hay mucho que hacer.
La otra interacción es leer mensajes nuevos del servidor. Para hacer esto a través de la red de manera efectiva, el cliente le dice al servidor de qué mensaje le gusta leer. El servidor pasará los mensajes desde ese momento (ID) al cliente.
Como muestra esto, desde el ciclo "interminable" al principio, ahora se ha convertido en un sistema basado en eventos con llamadas remotas. Como las llamadas remotas son costosas, es mejor hacer que puedan transferir mucha información con una conexión. Parte de eso ya está en el pseudo código, ya que es posible enviar uno o varios mensajes al servidor y recibir cero o más mensajes del servidor a la vez.
La implementación ideal sería tener una conexión con el servidor que permita leer y escribir mensajes en dúplex completo. Sin embargo, aún no existe esa tecnología en javascript. Estas cosas están en desarrollo con Websockets y APIs de Webstream y similares, pero por el momento vamos a ver las cosas simples y ver lo que tenemos: solicitudes HTTP sin estado, algunas PHP en el servidor y una base de datos MySQL.
La secuencia de mensajes se puede representar en una tabla de base de datos que tiene una clave única de incremento automático para el ID y otros campos para almacenar el mensaje.
El script de transacción de escritura simplemente se conectará a la base de datos, insertará los mensajes y devolverá los ID. Esa es una operación muy común y debería ser rápida (mysql tiene una especie de puente de Memcache que debería hacer que la operación de la tienda sea aún más rápida y conveniente).
El script de transacción de lectura es igualmente simple, simplemente leerá todos los mensajes con un ID más alto que el que se le pasó y lo devolverá al cliente.
Mantenga estos scripts lo más simples posible y optimice el tiempo de lectura/escritura en la tienda, para que puedan ejecutarse rápidamente e incluso chateando en HTTP simple.
Aún así, su servidor web y la conexión global a Internet pueden no ser lo suficientemente rápidos (aunque hay keep-alive).
Sin embargo, HTTP debería ser lo suficientemente bueno por el momento para probar si su sistema de chat está funcionando realmente sin bucles, ni cliente, ni servidor.
También es bueno mantener los servidores muertos de forma simple, porque cada cliente confía en ellos, por lo que deberían hacer su trabajo y eso es todo.
En cualquier momento puede cambiar el servidor (u ofrecer diferentes tipos de servidores) que pueden interactuar con su cliente de chat al darle al cliente de chat diferentes implementaciones de las funciones de envío y recepción. P.ej. Veo en su pregunta que está usando un cometa, esto debería funcionar también, probablemente sea fácil implementar directamente el servidor para el cometa.
Si en el futuro los websockets son más accesibles (lo que podría no ser el caso debido a consideraciones de seguridad), también puede ofrecer otro tipo de servidor para websockets. Siempre que la estructura de datos de la transmisión esté intacta, funcionará con diferentes tipos de servidores uno al lado del otro. La base de datos se ocupará de la congruencia.
Espero que esto sea útil.
Así como una nota adicional: HTML5 ofrece algo llamado Stream Updates with Server-Sent Events con un online demo y PHP/JS sources. La característica HTML 5 ya ofrece un objeto de evento en javascript que podría usarse para crear una implementación ejemplar de transporte de cliente de chat.
+1, esta es la única respuesta (hasta ahora) que no solo sugiere un enfoque diferente para el bucle infinito, sino que proporciona información sobre cómo crear un intercambio de mensajes dúplex completo (o emulado) basado en la web. –
+1 solo porque quien escribe tanto? Quiero decir, he leído manifiestos que son más cortos. He tenido viajes más cortos al DMV. He tenido desayunos más cortos con gemelos de 2 años. ¡Bromas aparte, lindos detalles y pensamientos! – iND