Vous êtes sur la page 1sur 11

Sockets en PHP

Sockets en PHP

2014
Alexander Eberle

Autor: Alexander Eberle

Blog.std-io.com

2014

Sockets en PHP

Sockets en PHP
Contenido
Notas del autor

Introduccin

Qu son los sockets?


3.1 Arquitectura Cliente/Servidor
3.2 Qu utilidad tienen sockets en php?
3.3 Detalles finales

3
3
4
4

Dependencias iniciales

PHPSocketMaster como cliente


5.1 Introduccin
5.2 Creando el cliente
5.3 Realizando distintas acciones
5.4 Cliente SocketWeb

5
5
5
7
8

PHPSocketMaster como servidor


6.1 Creando el servidor
6.2 Creando el cdigo para cada nuevo cliente
6.3 Realizando el cdigo principal
6.4 Resumen
6.5 SocketWeb

8
8
9
9
10
10

Otros usos de PHPSocketMaster

10

Posibles problemas

11

Alexander Eberle

2014

Sockets en PHP

Introduccin
1. Notas de autor
En ste documento utilizaremos la versin actual estable de PHP Socket Master (v0.4), aunque es
probable que veas este documento en una fecha muy superior, por lo que posiblemente la versin nueva
sea otra; por ste motivo, se enlazarn todas las referencias a la wiki del proyecto, para que puedes
acceder a las descripciones actualizadas de la biblioteca.
Adems, el autor de ste documento asume que t, como lector, posees conocimientos sobre el lenguaje
PHP.
2. Introduccin
La idea de este documento es demostrar las funcionalidades bsicas de PHPSocket Master y cmo utilizar
sockets en php.
La razn por la que se usa una biblioteca externa a php para manipular sockets, es que el control nativo
de php para manipular sockets es horroroso, y bastante complicado de utilizar de forma robusta y
correcta. Por otro lado PHPSocketMaster nos provee de las herramientas necesarias para hacer un
software robusto y funcional bajo muchsimas circunstancias.
3. Qu son los sockets?
A menudo, las aplicaciones desean conectarse a otras [aplicaciones] en otras pc a travs de una red (ya
sea internet, o una red local), para lo cual se utilizan sockets. Los sockets son conectores entre dos partes:
una de ellas es el cliente (aqul programa que desea conectarse a otro) y la otra parte, es el servidor
(aquel programa que espera las conexiones entrantes de la gente que se desea conectar a l).
Sockets veremos por todas partes, sockets hay en un navegador de internet, sockets hay en un servidor
web, sockets hay en el sistema de actualizaciones de Windows, tambin los hay en cualquier lugar donde
una pc se conecte a otra.
3.1. Arquitectura Cliente/Servidor
El funcionamiento de todos los sockets es el siguiente: un cliente que es el que se conecta, y un servidor
que es el que escucha, el mismo puede aceptar una cantidad limitada de conexiones o una cantidad
infinita (sin especificacin), o simplemente uno.

Entonces deducimos que Apache (o cualquier otro webserver) tiene un socket a la escucha (esperando
conexiones entrantes) y que nuestro navegador es uno de los miles de navegadores que establecern una
conexin, pedirn un archivo y luego finalizarn la conexin.
Ahora bien, en otros tipos de programas los sockets no establecen conexiones a largo plazo. Por el
contrario un servidor chat por ejemplo, los sockets permanecen abiertos enviando y recibiendo mensajes
que se envan desde y hacia un servidor, luego el servidor que recibe los mensajes los distribuye por el
resto de las pc conectadas.

2014

Alexander Eberle

Veamos el sistema de las pginas web: tu navegador se conecta a un servidor mediante el socket, y le
pide al servidor que le enve X archivo; el servidor por su parte, carga el archivo en memoria y se lo enva
al cliente, para que ste lo dibuje para la persona que lo est viendo.

Sockets en PHP

3.2. Qu utilidad tienen sockets en php?


Con sockets puedes conectarte desde tu programa hacia cualquier servidor y establecer el protocolo que
sea necesario; por ejemplo, IRC tiene un protocolo que seguir, una vez se establece la conexin del cliente
al servidor irc, ste tiene que mandar unos datos de base, el servidor irc le responder con ms datos del
servidor en el que se encuentra y luego el cliente es libre de unirse a canales, enviar mensajes y recibir
mensajes. Puedes entonces, hacer tranquilamente, clientes de irc, servidores de chats y lo que quieras;
incluso puedes crear tu propia librera cURL pero escrita en php.
3.3. Detalles finales
Es probable que ests leyendo este documento a sabiendas de lo que es un socket y quiz tengas dudas
de si un socket en php es diferente a un socket en otro lenguaje; y la realidad es que no, en todos los
lenguajes los sockets funcionan prcticamente de la misma manera, y se puede establecer una conexin
de un socket entre un programa de un lenguaje y otro, de un lenguaje diferente.
Y los famosos sockets webs y demaces, son simplemente sockets que tienen un protocolo que seguir una
vez establecida la conexin, tal como es en websockets el tema del handshake y luego enmascarar y
desenmascarar los mensajes.
Clientes Sockets
4.

Dependencias iniciales

Para trabajar con sockets en php uso la librera PHPSocketMaster (una librera de desarrollo propio que
lleva al menos 3 meses en desarrollo, con su versin actual (0.4), planificando una futura versin final
1.0; advirtiendo que, en realidad, no va a ser la versin final sino que tendr la estructura definitiva.
Esta librera tiene la funcionalidad de trabajar con Sockets comunes pero tambin con Sockets Webs
encargndose de manipular internamente los handshake y enmascaramientos de los datos enviados sin
que tengas nada que ver; para ti la diferencia entre sockets y sockets webs ser simplemente de escribir
una constante en la utilizacin de una funcin clave (veremos ms adelante ste hecho).
Los sockets webs son aquellos creados por javascript haciendo uso de los sockets webs definidos por la
W3C, el resto de los sockets son sockets comunes y corrientes incluidos los del servidor web, se les llama
sockets webs porque son creados desde una pgina web hacia otro lugar.

Una vez descargado, lo que nos interesa poner en el directorio de nuestro proyecto es la carpeta del zip
llamada src (luego hay carpetas con ejemplos, y pruebas). Te recomiendo poner esa carpeta src con
el nombre de PHPSocketMaster dentro del directorio de tu proyecto, dado que src es la carpeta que
contiene los archivos del ncleo de PHPSocketMaster; luego debes incluir el archivo iSocketMaster.php de
esa carpeta, ya sea para usar sockets webs, como normales, ya sea en modo cliente como en servidor.
require(src/iSocketMaster.php);
Una vez que tienes incluido este archivo en tu cdigo ya es posible utilizar PHPSocketMaster.

2014

Alexander Eberle

Pueden descargar PHPSocketMaster desde aqu, ver la wiki del proyecto con la documentacin
actualizada desde aqu, y el repositorio del cdigo en github desde aqu.

Sockets en PHP

5. PHPSocketMaster como cliente


5.1. Introduccin
Es posible que quieras utilizar los sockets para conectarte a algn lugar, por ejemplo, para acceder a un
servidor web y obtener un html, (o a un servidor de irc).
Para eso utilizaremos un socket y lo conectaremos al lugar, luego enviaremos la peticin y todos felices.
5.2. Creando el cliente
PHPSocketMaster funciona en forma de objetos y eventos; en consecuencia, lo primero que tenemos que
crear es lo que har nuestro socket o programa cuando ocurran ciertos eventos tales como cuando se
realice correctamente la conexin, se reciba un mensaje, o lo que fuera.
Para eso crearemos una clase (recomiendo ponerla en otro archivo para no mezclar todo) que
representar a nuestro socket:

class Cliente extends PHPSocketMaster\SocketMaster


{
}
Como vern, creamos una clase llamada cliente que extiende la clase SocketMaster (al principio se escribe
PHPSocketMaster\ porque PHPSocketMaster utiliza un namespace, (aunque se podra establecer el
namespace de entrada y as no necesitarlo, luego tendramos una serie de agregados extras para poder
acceder a los namespaces por defecto y otros namespaces).
A esta clase le agregaremos las funciones que sern ejecutadas automticamente cuando ocurra alguna
accin en nuestro socket (osea cuando se conecte satisfactoriamente, cuando se reciba un mensaje,
cuando se desconecte, u ocurra un error).
public function onConnect() {}

Pueden ver todos los eventos que existen en la versin actual de PHPSocketMaster aqu (documentacin
oficial y actualizada) ya que probablemente este documento -con el tiempo- no contenga nuevas
funciones o contenga funciones de eventos inexistentes. A la fecha de hoy, el mismo se encuentra
actualizado.

2014

Alexander Eberle

Es la funcin por defecto diseada para ejecutarse cuando se realice la conexin satisfactoriamente (es
importante establecer absolutamente TODAS las funciones de eventos aunque no hagan nada, ya que los
eventos ocurrirn de igual forma; entonces debe existir la funcin que ser llamada automticamente. Si
no se definen todas las funciones, php generar un fatal error en el momento que se trate de ejecutar el
cdigo ya sea que ocurra o no el evento, evitando que funcione).

Sockets en PHP

Entonces quedara as:


class Socket extends PHPSocketMaster\SocketMaster
{

public function onConnect() {}


public function onDisconnect()
{
}
public function onReceiveMessage($message)
{
}
public function onError($errorMessage)
{
}
public function onNewConnection(SocketBridge $socket) { }
}
Como puede observarse, hay varios eventos; los que nos interesan, sern onConnect, onDisconnect,
onError y onReceiveMessage.
Los utilizaremos para mostrar mensaje en cada uno de los eventos, para poder ver si nuestro cdigo est
funcionando, si hay errores, etc.
class Socket extends PHPSocketMaster\SocketMaster
{

Alexander Eberle

public function onConnect() { echo Socket Conectado; }


public function onDisconnect()
{
echo Socket Desconectado;
}
public function onReceiveMessage($message)
2014

Sockets en PHP

{
echo Mensaje recibido: .$message;
}
public function onError($errorMessage)
{
echo :( ocurri un error:. $errorMessage;
}
public function onNewConnection(SocketBridge $socket) { }
}
Simplemente escribimos una serie de mensajes, entonces cuando nuestro socket se desconecte, se
conecte o de un error mostrar dichos mensajes. Tambin cuando nuestro socket reciba un mensaje lo
mostrar. sta es slo una clase de ejemplo, puedes utilizar otras cosas para realizar las tareas de cada
uno de los eventos.
Una vez que tenemos escrito las acciones que realizar nuestro programa cuando ocurran los eventos,
escribiremos el cdigo que ser ejecutado no bien se ejecute el programa:
$socketCliente = new Cliente(google.com, 80);
Con esto, construimos una instancia de la clase que hicimos ms arriba. En realidad estamos creando un
socket con los eventos especificados arriba, el primer parmetro que se le pasa al constructor es la
direccin ip o dominio del pc al que nos queremos conectar (esto puede ser uno local, o uno de internet si
tenemos acceso a internet).
Ahora que tenemos creado nuestro socketCliente y estn especificados todos los eventos (las tareas que
realizar cuando ocurra cada cosa), realizaremos la conexin, al servidor que establecemos:
$socketClient->connect();

5.3. Realizando distintas acciones


Ahora, que est est conectado enviar un mensaje escribiendo:
$socketClient->send(Mensaje);
Tambin se puede hacer desde la clase cliente llamando a $this->send(Mensaje);

$socketClient->refresh();
La cual devolver un boolean, advirtiendo si hubo cambios de estado. Adems, si existiesen esos cambios
se llamarn a los eventos correspondientes (esta funcin revisa el estado en el momento, por lo que
debes revisar constantemente cambios en el estado del socket para advertirlos, es muy probable que en

2014

Alexander Eberle

Tambin, podemos ver si se recibieron nuevos mensajes, el socket se cerr, ocurri un error o lo que sea
llamando a la funcin:

Sockets en PHP

futuras versiones se agregue una funcin refreshLoop -que una vez que llames la funcinautomticamente revisar constantemente cambios en el socket y llamar a los eventos
correspondientes. Es til, si realizaras el resto de las tareas desde las funciones de eventos y no desde el
cdigo principal.
Puede revisar la lista de funciones del socket desde aqu (actualizada).
De esta manera, nosotros podemos enviar con send una peticin http a un servidor http como el de una
pgina web, y as obtener el contenido de la pgina web (puede encontrar el RFC del protocolo HTTP para
saber el formato con el cual enviar los mensajes para hacer la peticin). Cuando el servidor responda con
el contenido de la web que solicitamos ser ejecutada la funcin onReciveMessage y su parmetro
contendr la respuesta.
5.4. Cliente SocketWeb
Actualmente en la versin 0.4 no se incluye un cliente que responda al protocolo websocket, dado que es
muy poco probable que necesites crear un socket cliente web. El soporte socket web es para
PHPSocketMaster como servidor, donde puedes recibir conexiones desde sockets de una pgina web.

Servidores con sockets


6. PHPSocketMaster como servidor
6.1. Creando el servidor
Ahora bien, imaginemos que su aplicacin php -por ejemplo, ejecutada en consola- desea recibir nuevas
conexiones de programas externos en un puerto especfico, en otras palabras: pondremos un socket a
esperar (escuchar) nuevas conexiones entrantes por ese puerto.
Por lo que crearemos una clase igual a la del cliente, pero sta representar al socket que est esperando
las conexiones, pero en este caso solo nos importa el evento onNewConnection que ser ejecutado
cuando se est tratando de conectar otro programa a nuestro socket.
Dicho evento, recibe como parmetro $socket que ser un nuevo socket diferente al actual, y ste ser el
que tenga la conexin nueva, mientras el socket original que se encontraba esperando conexiones, se
quedar a esperar nuevas conexiones, de esta forma cada nueva conexin de otra pc, estar
representada por su propio socket, o instancia de socket.
El parmetro de dicha funcin debera ser almacenado en algn lado, en los ejemplos del cdigo original,
puedes ver como se almacenan utilizando una clase esttica externa (vase aqu).

Alexander Eberle

Un ejemplo de como quedara:


class Receptor extends PHPSocketMaster\SocketMaster
{
}

2014

Sockets en PHP

6.2. Creando el cdigo para cada nuevo cliente


Una vez que escribimos la clase que representar al socket que se encuentra a la espera de conexiones
entrantes, hay que escribir el cdigo de los sockets que sern las nuevas conexiones (aquellos que reciban
y enven mensajes).
class newClient extends PHPSocketMaster\SocketEventReceptor
sta clase representar a nuevos clients o conexiones que se establezcan satisfactoriamente, nuevamente
tenemos que escribir las funciones para los eventos -que en general son casi las mismas que en la primer
clase-. No es necesario definir la funcin onNewConnection (ya que bajo ningn contexto los sockets
creados por nuevas conexiones recibirn otras conexiones o.O), siendo sta una excepcin.
Puedes ver con detalle las funciones que tiene SocketEventReceptor aqu, esta nueva clase que debe
contener los eventos de cada socket nuevo en particular, tiene pequeas diferencias con respecto a la
clase cliente en su forma de trabajar; por ejemplo, desde un evento onReciveMessage($message) no
podemos enviar un mensaje usando:
$this->send(lalala);
Antes, en la clase de cliente si lo podamos hacer, pero aqu tenemos que primero obtener la instancia
SocketMaster de esta forma:
$this->getBridge();
Que para el caso anterior (enviar un mensaje) podemos poner:
$this->getBridge()->send();
Luego de getBridge, s tenemos acceso a todas las funciones de sockets como en el caso del apartado
anterior (clientes).
6.3. Realizando el cdigo principal
Ahora bien, asumiendo que tenemos las dos clases de las secciones anteriores, que representan los
eventos para el socket que estar a la escucha y los eventos para los sockets nuevos que se creen cuando
alguien se conecte a nosotros, tenemos que crear el cdigo que gestiona todo esto:
$socketReceptor = new Receptor('localhost', '2026');
A este constructor como parmetro le enviamos el dominio local (localhost o 127.0.0.0) y el puerto en el
cual esperaremos las conexiones.

$socketReceptor->refreshListen($socketCliente);
El parmetro de esta funcin debe ser una instancia de la clase newClient ya que contendr un nuevo
cliente cuando ocurra una nueva conexin.
Y adems, tenemos que refrezcar el estado de cada cliente creado (para lo cual debemos tener guardados

2014

Alexander Eberle

Luego lo ponemos a la escucha:


$socketReceptor->listen();
Luego tenemos que crear un bucle en el cual se refresque el estado del socket a la escucha

Sockets en PHP

todos los clientes creados con el evento onNewConnection()


6.4. Resumen
Para crear un servidor que escuche nuevas conexiones necesitamos dos clases diferentes: una que
representar al socket que se encuentra esperando nuevas conexiones (sta debe ser extend de
SocketMaster) y una clase que representa a cada una de las nuevas conexiones (sta debe ser extend de
SocketEventReceptor). En la primera clase lo que nos importa es el evento onNewConnection ya que se
ejecuta cuando se recibe una nueva conexin entrante. Mientras que en la segunda clase nos importan
los eventos de error, de desconexin, de recibir mensajes, ya que se tratar de cada uno de los sockets
conectados a nosotros.
En trminos generales la clase que representa las conexiones nuevas, es muy parecida a una clase cliente
como lo vimos al principio de este tutorial, la diferencia es que si se quisiera acceder a una de las
funciones internas de SocketMaster como lo es send, primero debemos obtener un puente entre la clase
SocketEventReceptor y SocketMaster utilizando la funcin getBridge; quedando entonces el acceso a
funciones como send de esta forma:
$this->getBridge()->send(mensaje);
Puede ver un ejemplo de como crear un servidor de sockets aqu o en la carpeta de ejemplos.
6.5. SocketWeb
La diferencia entre un servidor a la escucha normal para sockets comunes y uno para socket web es
simplemente que cuando se llame a la funcin:
$socketReceptor->refreshListen($socketCliente);
Hay que agregar una constante extra entre los parmetros (SCKM_WEB) quedando entonces as:
$socketReceptor->refreshListen($socketCliente, SCKM_WEB);
Queda, entonces, establecido que las nuevas conexiones entrantes sern de tipo socketweb y
estableciendo esto, los sockets web funcionarn perfectamente; pero debes tener en cuenta que sockets
normales no sabrn como manejar el protocolo. Internamente PHPSocketMaster se encargar de todos
los detalles con respecto a enmascarar y desenmascarar mensajes, sin que tu debas hacer nada ms.
Puede ver un ejemplo de como crear un servidor chat de sockets web aqu o en la carpeta de ejemplos.

7. Otros usos de PHPSocketMaster


PHPSocketMaster incorpora otras herramientas adems de websockets y sockets comunes. Tambin
existe HTTPClient que es una interface entre sockets normales con el protocolo http incorporado, algo
muy parecido a usar cURL para obtener pginas web o enviar peticiones post.
Puede ver ms detalles aqu aunque en la versin 0.4 esta herramienta an se encuentra en estado de

2014

Alexander Eberle

ltimos detalles

10

Sockets en PHP

pruebas.
8. Posibles problemas
Es posible que tengas problemas al ejecutar un cdigo usando socket master, ya que ste depende de la
dll socket_php.dll; si llegas a tener este problema revisa que en el archivo php.ini se estn cargando los
archivos.
Tambin puede que tengas problemas al usar socket webs -desde la funcin onConnect de javascript si se
enva un mensaje en ese momento- generndose un error ya que an no se estableci el protocolo
handshake.
Por otra parte dependiendo de su versin de php, puede que tengas un problema con los Traits (los
mismos pueden ser omitidos e incorporados directamente a la clase, pero el desarrollo oficial no da
soporte a esta medida, de modo que corre por tu cuenta, aunque recomendamos actualices tu versin de
php)
En versiones anteriores de PHPSocketMaster podas tener problemas si tu versin no era php5.6; ya que
el trait singleton requiere de la ultima versin al da para funcionar, por lo que se implement una
versin de singleton compatible con versiones viejas de php; no obstante, puede que en un futuro esta
compatibilidad sea eliminada por lo que si tienes una versin vieja de php debe utilizar este archivo
9. End of file
Como despedida quiero agradecer a todos los lectores de mi blog, a la gente de underc0de.org que
siempre apoya mis documentos, trabajos, etc. Y proponerles que se den una vuelta por mi blog:
http://blog.std-io.com seguro encuentran cosas muy interesantes para leer.
Tambin puedes ver el repositorio oficial de PHPSocketMaster y ofrecer cualquier sugerencia que tengas
en mente.

Alexander Eberle

Como agradecimiento final, quiero agregar a Gabriela de underc0de que se tom un gran trabajo para
corregir mi documento.

2014

11

Vous aimerez peut-être aussi