Implementación de WebSocket y Socket de PHP para desarrollar una sala chat

  • 18 Ene 2016
  • PHP, WebSocket, JavaScript, Bootstrap

La idea es desarrollar una sala de chat web con la posibilidad de invitar un usuario a una sala privada donde solo el usuario anfitrión y el usuario invitado puedan intercambiar mensajes. Para realizarlo utilizaremos dos herramientas que implementan WebSocket:

Inspirándonos en el artículo de Saran Chamling vamos a utilizar sus dos archivos. Uno para el lado servidor, el otro para el cliente. La comunicación entre ambos es a través de mensajes. Todo lo que pongamos en ellos nos permitirá realizar cualquier tipo de aplicación, como por ejemplo, juegos online.

Al trabajo de Saran agregamos un poco  más de información sobre cada cliente. Esto nos permitirá crear la sala privada. Por ejemplo:

Array
(
    [a19l2hd08q72eacc189tpk1n9i00hn0kojb87q8352ilqee10gp0] => Array
        (
            [name] => Edu
            [socket] => Resource id #16
            [users] => Array
                (
                    [0] => rc7b7iht0hoa8obs4covqoblunumpudk4sedko2ar10ihrmmgeq1
                )
        )
)

Agregaremos además un nuevo tipo de mensaje para manejar las invitaciones y si son aceptadas o no.

Arrancar el servicio

El archivo server.php contiene 2 variables que debemos modificar (o no) de acuerda al ambiente donde lo estemos ejecutando.

$host = 'localhost';
$port = '9000';

Para arrancar el servicio, abrir la consola y ejecutar:

php server.php

Cliente con Bootstrap y WebSocket

Para el desarrollo de la interfaz web le vamos a pedir una mano a Bootstrap. Hay muchos templates en el sitio de Bootstrap que pueden servir para comenzar a trabajar. Para identificar a cada uno de los usuarios utilizamos el identificador de la session de PHP y lo asignamos a una variable JS.

var user_sid = '<?php print session_id(); ?>';

El primer mensaje que el cliente enviará al servidor deberá contener su nombre y su session_id.

// set some vars
w.name = $('#name').val();
w.wsUri = "ws://localhost:9000/server.php";
w.websocket = new WebSocket(w.wsUri);

w.websocket.onopen = function(ev) {
  var msg = {
    name : w.name,
    sid : '<?php print session_id(); ?>'
  };
  w.websocket.send(JSON.stringify(msg));
  $('#message_box').prepend("<div class=\"system_msg\">Connected!</div>"); //notify user
  $('#connect').addClass('btn-default connected').removeClass('btn-primary').html('Disconnect');
}

Luego de crear la conexión permanente con el servidor encontraremos la función que se ocupará de recibir cada mensaje del servidor.

w.websocket.onmessage = function(ev) {
  var msg    = JSON.parse(ev.data);
  var type   = msg.type;
  var umsg   = msg.message;
  var uname  = msg.name;
  var ucolor = msg.color;
  var sid    = msg.sid;
  ....

Las operaciones de enviar y aceptar invitaciones serán fácilmente manejables a través del modal de Bootstrap.

La función sendMessage es la encargada de codificar el mensaje para luego ser enviado al servidor.

function sendMessage(mymessage){ 
    
    var to_users = new Array();
    $('input:checked').each(function(){
      to_users.push( $(this).attr('data-id') );
    });

    if(mymessage == ""){ //emtpy message?
      alert("Enter Some message Please!");
      return;
    }
    
    //prepare json data
    var msg = {
      message: mymessage,
      name: w.name,
      color : '<?php echo $colours[$user_colour]; ?>',
      sid : '<?php print session_id(); ?>',
      to_users: to_users
    };

    //convert and send data to server
    w.websocket.send(JSON.stringify(msg));
  }

Capturas de pantalla

WebSocket: El primer usuario se conecta

WebSocket: Se conecta el segundo usuario. Ambos ven al otro en la lista de usuarios conectados.

WebSocket: El usuario Emiliano envía una invitación a Franco

WebSocket: Franco es notificado de la invitación de Emiliano

WebSocket: Se notifica que el usuario ha aceptado la invitación