Advertisement
  1. Code
  2. PHP

Cómo crear un script de chat en vivo en PHP

Scroll to top
Read Time: 11 min

() translation by (you can also view the original English article)

En este artículo, analizaremos cómo puedes crear un script de chat en vivo en PHP. Si bien existen diferentes formas en las que podrías lograrlo, usaremos una implementación basada en sockets.

Si estás creando un sitio de comunidad que involucra la participación de los usuarios, es útil proporcionar una manera para que los usuarios puedan discutir ideas en tiempo real. Cuando se trata de la interacción en tiempo real entre usuarios, lo mejor es suministrar una especie de función de sala de chat en donde puedan reunirse y discutir sus ideas.

Hoy vamos a analizar cómo puedes implementar un chat en vivo en tu sitio web de PHP. Ya que es una función popular, existen muchos scripts de chat disponibles en el mercado que están listos para ser usados. Encontrarás una combinación de scripts de chat de PHP prémium y gratuitos de entre los que puedes elegir.

En este artículo, vamos a usar el módulo "Chat Using WebSocket and PHP Socket" (Chat mediante el uso de WebSocket y Socket de PHP), que está integrado en PHP y es totalmente de código abierto.

En la siguiente sección veremos cómo descargar y configurar el módulo "Chat Using WebSocket and PHP Socket".

Cómo descargar y configurar el módulo "Chat Using WebSocket and PHP Socket"

El módulo "Chat Using WebSocket and PHP Socket" está disponible en GitHub y, por lo tanto, puedes clonar el repositorio o descargar el archivo .zip del paquete.

Si quieres clonar el repositorio "Chat Using WebSocket and PHP Socket", puedes usar el siguiente comando en tu símbolo del sistema.

1
git clone https://github.com/sanwebe/Chat-Using-WebSocket-and-PHP-Socket.git

Por otro lado, si quieres descargar el archivo .zip, puedes descargarlo del repositorio oficial

El directorio Chat-Using-WebSocket-and-PHP-Socket contiene los archivos del paquete. Debes colocar este directorio dentro de la raíz de documentos de tu servidor web para poder acceder a él a través del navegador.

El paquete contiene dos archivos PHP, server.php e index.php y, para continuar, debemos configurar el valor del host en ambos archivos. Abre ambos archivos en tu editor de texto favorito y reemplaza el valor localhost con el nombre de host de tu servidor. Por supuesto, si estás trabajando en la máquina local con fines de prueba, no es necesario que lo modifiques.

Con estos cambios hemos terminado la configuración de nuestro módulo. Antes de que sigamos adelante y veamos cómo ejecutarlo, en la siguiente sección revisaremos los archivos server.php e index.php para comprender cómo funciona este módulo exactamente.

Cómo funciona el módulo "Chat Using WebSocket and PHP Socket"

El módulo "Chat Using WebSocket and PHP Socket" está basado en WebSockets. Veamos rápidamente qué es la API WebSocket:

La API WebSocket es una tecnología avanzada que permite abrir una sesión de comunicación interactiva bidireccional entre el navegador del usuario y un servidor. Con esta API puedes enviar mensajes a un servidor y recibir respuestas basadas en eventos sin tener que sondear al servidor para obtener una respuesta. (MDN)

Una vez que un navegador abre una conexión de socket web con el servidor web, dicho navegador puede realizar una comunicación bidireccional con ese servidor. Por lo tanto, puede enviar datos al servidor web con la ayuda del método send, y puede recibir datos del servidor web con la ayuda del controlador de eventos onmessage. Así que esa es la implementación de WebSockets en el lado del cliente.

En el lado del servidor, debemos usar las funciones de socket de PHP para abrir y enlazar sockets, escuchar conexiones de sockets entrantes, además de leer y enviar datos a todos los sockets disponibles.

Revisemos los fragmentos de código importantes que se encuentran en ambos archivos.

El archivo index.php

El archivo index.php es el responsable de mostrar la interfaz de usuario del chat y gestionar una conexión de socket con el servidor web.

Analicemos el siguiente fragmento de código, que es la parte más importante del archivo index.php.

1
<script language="javascript" type="text/javascript">  
2
    //create a new WebSocket object.

3
    var msgBox = $('#message-box');
4
    var wsUri = "ws://localhost:9000/demo/server.php";     
5
    websocket = new WebSocket(wsUri);
6
    
7
    websocket.onopen = function(ev) { // connection is open

8
        msgBox.append('<div class="system_msg" style="color:#bbbbbb">Welcome to my "Demo WebSocket Chat box"!</div>'); //notify user

9
    }
10
    // Message received from server

11
    websocket.onmessage = function(ev) {
12
        var response         = JSON.parse(ev.data); //PHP sends Json data

13
        
14
        var res_type         = response.type; //message type

15
        var user_message     = response.message; //message text

16
        var user_name         = response.name; //user name

17
        var user_color         = response.color; //color

18
19
        switch(res_type){
20
            case 'usermsg':
21
                msgBox.append('<div><span class="user_name" style="color:' + user_color + '">' + user_name + '</span> : <span class="user_message">' + user_message + '</span></div>');
22
                break;
23
            case 'system':
24
                msgBox.append('<div style="color:#bbbbbb">' + user_message + '</div>');
25
                break;
26
        }
27
        msgBox[0].scrollTop = msgBox[0].scrollHeight; //scroll message

28
29
    };
30
    
31
    websocket.onerror    = function(ev){ msgBox.append('<div class="system_error">Error Occurred - ' + ev.data + '</div>'); };
32
    websocket.onclose     = function(ev){ msgBox.append('<div class="system_msg">Connection Closed</div>'); };
33
34
    //Message send button

35
    $('#send-message').click(function(){
36
        send_message();
37
    });
38
    
39
    //User hits enter key

40
    $( "#message" ).on( "keydown", function( event ) {
41
      if(event.which==13){
42
          send_message();
43
      }
44
    });
45
    
46
    //Send message

47
    function send_message(){
48
        var message_input = $('#message'); //user message text

49
        var name_input = $('#name'); //user name

50
        
51
        if(message_input.val() == ""){ //empty name?

52
            alert("Enter your Name please!");
53
            return;
54
        }
55
        if(message_input.val() == ""){ //emtpy message?

56
            alert("Enter Some message Please!");
57
            return;
58
        }
59
60
        //prepare json data

61
        var msg = {
62
            message: message_input.val(),
63
            name: name_input.val(),
64
            color : '<?php echo $colors[$color_pick]; ?>'
65
        };
66
        //convert and send data to server

67
        websocket.send(JSON.stringify(msg));    
68
        message_input.val(''); //reset message input

69
    }
70
</script>

En primer lugar, la llamada new WebSocket(wsUri) abre una conexión de socket con el servidor web. Una vez que hemos abierto una conexión de socket, definimos diferentes controladores de eventos para capturar diferentes tipos de eventos.

Controladores de eventos

El objeto WebSocket permite principalmente cuatro eventos: onopen, onmessage, onerror y onclose. Nuestro script ha definido controladores de eventos para todos ellos.

El controlador de evento onopen se usa para mostrar un mensaje de bienvenida a los usuarios.

1
websocket.onopen = function(ev) { // connection is open

2
    msgBox.append('<div class="system_msg" style="color:#bbbbbb">Welcome to my "Demo WebSocket Chat box"!</div>'); //notify user

3
}

A continuación, el controlador de evento onmessage se usa para mostrar mensajes recibidos desde el servidor web. Básicamente, este analiza los datos JSON recibidos del servidor, prepara el código HTML y lo agrega al cuadro del chat.

1
websocket.onmessage = function(ev) {
2
    var response         = JSON.parse(ev.data); //PHP sends Json data

3
    
4
    var res_type         = response.type; //message type

5
    var user_message     = response.message; //message text

6
    var user_name         = response.name; //user name

7
    var user_color         = response.color; //color

8
9
    switch(res_type){
10
        case 'usermsg':
11
            msgBox.append('<div><span class="user_name" style="color:' + user_color + '">' + user_name + '</span> : <span class="user_message">' + user_message + '</span></div>');
12
            break;
13
        case 'system':
14
            msgBox.append('<div style="color:#bbbbbb">' + user_message + '</div>');
15
            break;
16
    }
17
    msgBox[0].scrollTop = msgBox[0].scrollHeight; //scroll message

18
19
};

Puedes usar el controlador de evento onerror para gestionar errores y mostrar los mensajes de error apropiados a los usuarios.

1
websocket.onerror    = function(ev){ msgBox.append('<div class="system_error">Error Occurred - ' + ev.data + '</div>'); };

Finalmente, el controlador de evento onclose se usa para notificar que la conexión está cerrada.

1
websocket.onclose     = function(ev){ msgBox.append('<div class="system_msg">Connection Closed</div>'); };

El método send

Si se usan controladores de eventos para escuchar y actuar ante eventos del lado del servidor, el método send te permite enviar datos desde un navegador al servidor web.

En el archivo index.php hemos definido la función send_message, que es llamada cuando los usuarios hacen clic en el botón Enviar o cuando presionan la tecla Intro. La función send_message gestiona la lógica del envío de datos al servidor web.

1
function send_message(){
2
    var message_input = $('#message'); //user message text

3
    var name_input = $('#name'); //user name

4
    
5
    if(message_input.val() == ""){ //empty name?

6
        alert("Enter your Name please!");
7
        return;
8
    }
9
    if(message_input.val() == ""){ //emtpy message?

10
        alert("Enter Some message Please!");
11
        return;
12
    }
13
14
    //prepare json data

15
    var msg = {
16
        message: message_input.val(),
17
        name: name_input.val(),
18
        color : '<?php echo $colors[$color_pick]; ?>'
19
    };
20
    //convert and send data to server

21
    websocket.send(JSON.stringify(msg));    
22
    message_input.val(''); //reset message input

23
}

Como puedes ver, hemos llamado al método websocket.send para enviar datos al servidor web.

El archivo server.php

El archivo server.php es el responsable de escuchar las conexiones de socket entrantes, leer datos y enviarlos a todos los clientes. En esta sección analizaremos fragmentos de código importantes contenidos en el archivo server.php.

El primer paso es crear una conexión de socket usando la función socket_create.

1
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

A continuación, enlazaremos un socket a un puerto específico y comenzaremos a escuchar para detectar alguna conexión en ese socket.

1
socket_bind($socket, 0, $port);
2
socket_listen($socket);

Además, hemos inicializado la variable $clients, que contiene diferentes conexiones de socket de distintos usuarios.

1
$clients = array($socket);

Finalmente tenemos el bucle while, que se ejecuta infinitamente y hace dos cosas importantes, como se explica a continuación.

En primer lugar, comprueba si existe una nueva conexión de socket. Si hay una nueva conexión de socket, esta se agrega a la variable global $clients. También notifica a otros clientes sobre esta nueva conexión. Básicamente, otros usuarios reciben una notificación cuando un nuevo usuario se une a la sala de chat.

1
//check for new socket

2
if (in_array($socket, $changed)) {
3
    $socket_new = socket_accept($socket); //accept new socket

4
    $clients[] = $socket_new; //add socket to client array

5
    
6
    $header = socket_read($socket_new, 1024); //read data sent by the socket

7
    perform_handshaking($header, $socket_new, $host, $port); //perform websocket handshake

8
    
9
    socket_getpeername($socket_new, $ip); //get ip address of connected socket

10
    $response = mask(json_encode(array('type'=>'system', 'message'=>$ip.' connected'))); //prepare json data

11
    send_message($response); //notify all users about new connection

12
    
13
    //make room for new socket

14
    $found_socket = array_search($socket, $changed);
15
    unset($changed[$found_socket]);
16
}

A continuación, recorre todos los sockets conectados y revisa si hay datos entrantes. Si se han recibido datos en algún socket, el bucle lee esos datos usando la función socket_recv. Los datos recibidos están en formato JSON y, por lo tanto, necesitamos decodificarlos en primer lugar. Finalmente se llama a la función send_message, que envía estos datos a todos los sockets conectados.

1
//loop through all connected sockets

2
foreach ($changed as $changed_socket) {	
3
	
4
	//check for any incomming data

5
	while(socket_recv($changed_socket, $buf, 1024, 0) >= 1)
6
	{
7
		$received_text = unmask($buf); //unmask data

8
		$tst_msg = json_decode($received_text, true); //json decode 

9
		$user_name = $tst_msg['name']; //sender name

10
		$user_message = $tst_msg['message']; //message text

11
		$user_color = $tst_msg['color']; //color

12
		
13
		//prepare data to be sent to client

14
		$response_text = mask(json_encode(array('type'=>'usermsg', 'name'=>$user_name, 'message'=>$user_message, 'color'=>$user_color)));
15
		send_message($response_text); //send data

16
		break 2; //exist this loop

17
	}
18
    ...
19
    ...
20
}

La función send_message tiene este aspecto:

1
function send_message($msg)
2
{
3
    global $clients;
4
    foreach($clients as $changed_socket)
5
    {
6
        @socket_write($changed_socket,$msg,strlen($msg));
7
    }
8
    return true;
9
}

Si algún usuario está desconectado, el siguiente código es el responsable de eliminar de la variable $clients al cliente de socket asociado con ese usuario. Además, todos los usuarios conectados también reciben una notificación sobre este evento.

1
$buf = @socket_read($changed_socket, 1024, PHP_NORMAL_READ);
2
if ($buf === false) { // check disconnected client

3
    // remove client for $clients array

4
    $found_socket = array_search($changed_socket, $clients);
5
    socket_getpeername($changed_socket, $ip);
6
    unset($clients[$found_socket]);
7
    
8
    //notify all users about disconnected connection

9
    $response = mask(json_encode(array('type'=>'system', 'message'=>$ip.' disconnected')));
10
    send_message($response);
11
}

Ya que el bucle while se ejecuta infinitamente, este revisa continuamente si existen nuevas conexiones y mensaje y, por lo tanto, todos los usuarios son notificados instantáneamente sobre eso.

Así que esa es la implementación de los sockets del lado del servidor. En la siguiente sección veremos cómo ejecutar este módulo.

Cómo ejecutar el chat usando el módulo "WebSocket and PHP Socket"

En primer lugar, tenemos que arrancar el servidor de sockets para que pueda comenzar a escuchar las conexiones entrantes.

Sigue adelante y ejecuta el archivo server.php en la línea de comandos, como se muestra en el siguiente fragmento de código. Esto debería arrancar el servidor de sockets.

1
$php -q server.php

Ahora debes visitar el archivo index.php en tu navegador. Dado que has colocado el directorio Chat-Using-WebSocket-and-PHP-Socket-master dentro de la raíz de documentos, deberías poder acceder a él a través de https://localhost/Chat-Using-WebSocket-and-PHP-Socket-master/index.php.

Deberías ver la siguiente interfaz de usuario.

Puedes abrir el URL https://localhost/Chat-Using-WebSocket-and-PHP-Socket-master/index.php desde otro navegador para simular una experiencia multiusuario. Recibirás una notificación sobre la nueva conexión de usuario.

Comienza a enviar mensajes en ambas pantallas y se te notificará al instante.

Como puedes ver, es bastante sencillo implementar un módulo de chat basado en sockets de PHP en tu sitio web. También hay otras maneras, como crear un módulo de chat basado en AJAX que sondee a un servidor continuamente para recibir nuevos mensajes de él, pero la implementación basada en sockets es más eficiente y no genera tanto tráfico en tu servidor, por lo que es preferible.

Conclusión

Hoy analizamos cómo puedes implementar un chat en vivo en PHP con la ayuda del módulo "Chat Using WebSocket and PHP Socket". Se trata de una implementación basada en sockets, y hemos discutido partes importantes de este módulo a lo largo del artículo.

También puedes leer sobre los scripts prémium de PHP para crear chats disponibles en CodeCanyon.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.