Un socket es un punto de comunicación entre dos máquinas.

Tipicamente los sockets BSD consisten en dos niveles de procesos de aplicación separados; un proceso (el cliente) realiza una conexión mientras que el segundo proceso (servidor) las acepta, a esto se le conoce como Modelo Cliente – Servidor.
Este tipo de socket permite trabajar realizando/esperando conexiones a puertos TCP.
Lo mismo que el anterior pero trabajando con paquetes UDP
O mejor conocidos como de bajo nivel, permiten trabajar con las cabeceras IP, TCP, UDP, construir nuestros propios packetes etc.. Por desgracia no veremos su implementación.
PHP no sólo nos ofrece la función “fsockopen” para tratar con sockets, también nos permite trabajar con Sockets BSD, del cuál he visto muy poca información.
Por fortuna para los usuarios de Linux los sockets BSD ya vienen habilitados, y si no, tendremos que recompilar nuestro php con la opción “—socket”.
Para los usuarios de Windows PHP no trae la extensión habilitada.
Para habilitar los sockets bsd seguir los siguientes 4 pasos:
Ya que tenemos habilitados los sockets en PHP sea en Windows o Linux nos dedicaremos ahora a su implementación! (Lo que tanto hemos esperado muchachos!)
Me pondría a explicar cada una de las funciones con sus prototipos para que todos pudieramos entender pero sería muy aburrido y pienso que es más fácil comprender/aprender con un buen código por lo tanto aquí les dejo un ejemplo de cómo conectar con algoritmatica
$sock = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
// Creamos un socket con socket_create, le pasamos como primer parámetro la constante del tipo de dominio a utilizar, luego el tipo de socket (SOCK_STREAM, SOCK_DGRAM, SOCK_RAW) y por ultimo el protocolo
$result = socket_connect($sock,gethostbyname(“www.algoritmatica.com”),80);
// Pasamos como primer parámetro el descriptor del socket creado, usamos gethostbyname para resolver el nombre de dominio (host) y por último indicamos que queremos conectar al puerto 80
// Creamos la petición HTTP
$header .= “HEAD / HTTP/1.0\r\n”;
$header .= “Host: www.algoritmatica.com”;
$header .= “Connection:Close”;
socket_write($sock,$header,strlen($header));
// Pasamos como primer parámetro el descriptor de socket, la petición http y su tamaño en bytes usando la función strlen.
while($respuesta = socket_read($sock,2048))
// Esperamos la respuesta y los datos.
{
echo $respuesta;
}
socket_close($sock);
// Cerramos socket y conexión.
Este ejemplo está extraído de la referencia de PHP
(que todos deberíamos tener a la hora de programar… agradezco el código!)
set_time_limit(0);
ob_implicit_flush();
$address = '192.168.1.3';
$port = 10000;
if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) < 0) {
echo "socket_create() failed: reason: " . socket_strerror($sock) . "\n";
}
if (($ret = socket_bind($sock, $address, $port)) < 0) {
echo "socket_bind() failed: reason: " . socket_strerror($ret) . "\n";
}
if (($ret = socket_listen($sock, 5)) < 0) {
echo "socket_listen() failed: reason: " . socket_strerror($ret) . "\n";
}
do {
if (($msgsock = socket_accept($sock)) < 0) {
echo "socket_accept() failed: reason: " . socket_strerror($msgsock) . "\n";
break;
}
/* Send instructions. */
$msg = "\nWelcome to the PHP Test Server. \n" .
"To quit, type 'quit'. To shut down the server type 'shutdown'.\n";
socket_write($msgsock, $msg, strlen($msg));
do {
if (false === ($buf = socket_read($msgsock, 2048, PHP_NORMAL_READ))) {
echo "socket_read() failed: reason: " . socket_strerror($ret) . "\n";
break 2;
}
if (!$buf = trim($buf)) {
continue;
}
if ($buf == 'quit') {
break;
}
if ($buf == 'shutdown') {
socket_close($msgsock);
break 2;
}
$talkback = "PHP: You said '$buf'.\n";
socket_write($msgsock, $talkback, strlen($talkback));
echo "$buf\n";
} while (true);
socket_close($msgsock);
} while (true);
socket_close($sock);
He dado una pequeña introducción a los sockets, el modelo cliente-servidor y sockets en PHP, sería interesante que para una próxima entrada escriba sobre sockets pero en C y su implementación en windows (winsockets).
¿Algún comentario o sugerencia? cualquier cosa será bienvenida! no dejes de comentar!
gracias.
Para mayor información:
http://www.php.net/manual/es/ref.sockets.php
hola probe tu codigo pero me lanza los siguientes errores cuando corro el servidor, utlizo wamp5
Estimada Yenny Colmenarez, primero que nada es un gusto que haya mujeres entrando al blog (Que por cierto he notado con son muchas
)
Bueno, segundo, el código no es mío, lo he tomado de la referencia de PHP.net, sin embargo has probado quitar los caracteres raros que salieron en el código?
<0 <-
Por que yo estoy probando el código y todo funciona perfecto
Mmm puedes cambair los argumentos de socket create así
socket_create(AF_INET, SOCK_STREAM,tcp)
y checa si no te funciona si no vuelve a probar con
socket_create(AF_INET,SOCK_STREAM,SOL_TCP)
y si NADA! entonces avisanos por aquí para que nos pongamos a checarlo bien
yo ahora estoy en el trabajo y te contesto así de rápido..
de todas formas estamos en contacto
y muchas gracias por avisar =)
Eduardo: Definitivamente, hace falta el foro para estas cuestiones =).
Un saludo y gracias por comentar.
hola como estas probe con las dos observaciones que me diste y tampoco funciona..
que podra ser??
Hola Yenny,
Acabo de arreglar el código (ya que salían caracteres raros en lugar del signo “menor que”).
Los errores que describes, son raros, en primer lugar porque ni siquiera te crea el socket.
Prueba este código y dime si te marca error:
<?PHP set_time_limit(0); ob_implicit_flush(); $address = '127.0.0.1'; $port = 85; $sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); if (($sock) < 0) { echo "socket_create() failed: reason: " . socket_strerror($sock) . "\n"; } socket_close($sock); ?>si todo va bien… no debería mostrarte nada.
Si te marca error, será mandinga, o el wamp, aunque no creo … ummmm
Ahora, con respecto al error del BIND, lo que te está diciendo es “Ya tienes un puerto abierto por otro programa, por lo que no puedo abrir ese puerto!”
Si el puerto ya está en uso, no lo podrás abrir de nuevo.
Prueba poner otro puerto, por ejemplo el 86, 87, 88, si con esos no te funciona entonces no sé, pero la IP original que puso Amir es de su LAN.
Todos los demás errores se derivan de estos dos primeros, una vez que arregles esas dos funciones todo lo demás debería funcionarte.
Si sigue sin funcionar vuelve a postear le daremos una revisada mas profunda.
Nos avisas
gracias.
Hola a todos, este blog me parece buenísimo, pues es de gran ayuda para todos los que iniciamos en esto de los socket con php.
He probado el mismo ejemplo y le he hecho algunas modificaciones como esta:
if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false) { echo "socket_create() falló: motivo: " . socket_strerror($sock) . "\n";} if (($ret= socket_bind($sock, $direccion, $puerto))=== false) { echo "socket_bind() falló: motivo: " . socket_strerror($ret) . "\n"; } if (($ret = socket_listen($sock, 5)) === FALSE) { echo "socket_listen() falló: motivo: " . socket_strerror($ret) . "\n"; } do { if (($mens_sock = socket_accept($sock)) === false) { echo "socket_accept() falló: motivo " . socket_strerror($mens_sock) . "\n"; break;tengo el mismo error que Yenny Colmenarez, exepto por la ultima linea que me aparece:
Ya probe el ejemplo que nos pone Eduardo y al parecer todo va bien, de hecho mi problema no parece ser el socket_create, sino las otras funciones como el socket_bind, socket_listen, socket_acept y otras funciones similares, pues he probado varios ejemplos y el mensaje siempre es el mismo. Utilizo el xampp versión 2.5 y php versión 5.
Por favor necesito de la ayuda de todos uds. Gracias por anticipado y sigan creando más blogs como éste.
Hola Mar,
el error del bind está en los parametros que le estas pasando:
socket_bind($sock, $direccion, $puerto))
$direccion y $puerto, deben ser una direccion IP que pueda ser abierta (por ejemplo, la tuya local!) y el puerto es lo que mas problemas puede dar.
¿Que puerto debes abrir? Hay que estar atento con esto, porque yo la primera vez que ejecuté el código, le puse el puerto 80 y me marcó error (porque ese puerto ya lo tengo abierto).
Puse el puerto del ejemplo de Amir, el 10000, y también me marcó error (ni idea pero supongo que debo tener otro programa escuchando en ese puerto), puse los puertos 81,82,83,84… esos si me dejó abrirlos.
Los demás errores, del listen y accept, tienen que ver con el bind… una funcion falla y fallan todas las demás.
Espero haberte ayudado, Salu2.
Saludos Eduardo.
Gracias por responder a mi pregunta.En cuanto a lo del puerto tienes razon.El puerto 80 esta abierto, use otros como el 82,83,85, y funcionó por un segundo.La primera que llamo a telnet me envia:
Welcome to the PHP Test Server.
To quit, type ‘quit’. To shut down the server type ‘shutdown’
Y cuando pensé que todo iba muy bien(cosa de segundos), recibo en siguiente mensaje:
Se ha perdido la conexión con el host.
¿¿Alguien tiene idea de lo que pueda estar pasando?? Espero respuestas u otros ejemplos. Toda información me va caer muy bien. Saludos a todos los que visitan este blog. Hasta luego.
Hola , jeje entre a tu blog y me ha percido bueno, aunque con esto de los sockets tengo problemas para comprenderlo muy bien, mi pregunta va dirigida a que si se puede hacer un ping con ese tipo de funciones, gracias
Hola Angelica,
Efectivamente, puedes realizar un ping. Aunque con el solo hecho de “conectarte” a un servidor, podrias verificar si esa conexión es válida o no para saber si el servidor existe.
Salu2.
Hola de nuevo. Me gustaria saber como enviar datos(ya sea imagenes, datos,informacion confidencial, etc) de una pc a otra a través de internet, ya he realizado pruebas en una lan y funciona perfectamente, pero a través de internet no se como hacerlo. Es necesario abrir los puertos de módem o como?
Hola muchas gracias por tu respuesta, realmente lo que necesito es saber si mis clientes estan conectados (prendidos) para pdoer enviar archivos a ellos, los archivos los envio por ftp, si con el ping se que estan conectados, como puedo verificar los puertos, con lo mismo de los sockets?, perdon por las molestias gracias.
@Angelica,
Tendrías que tener un programa corriendo en las computadoras de tus clientes. Ese programa debería abrir un puerto X (previamente configurando el router/firewall para que deje abrirlo) y luego si, con los sockets BSD podrías verificar si ese host con ese puerto abierto existe.
Hola Amir.
Buscando información sobre Sockets, encontre este blog, el cual me pareció muy interesante.
Yo tengo la siguiente inquietud:
Me pidieron en el trabajo generar un XML con PHP y enviarlo a una aplicación JAVA vía socket. Y para ser sincero, no tengo idea de como hacer el envío.
Si pudieras orientarme, lo agradeceria mucho.
Saludos cordiales.
@Humberto:
Es simple, pon tu aplicación Java a escuchar en determinado puerto esperando por la comunicación
y ahora con PHP simplemente crea un socket, (socket_create) y usa socket_connect al host y puerto donde está corriendo tu app java y con socket_write envia el XML generado, sea manualmente o con las funciones para manipular XML’s
un saludo.
Ya luego tu app java parsea los datos recividos..
Buen dia, que tema tan interesante. los felicito
de antemano gracias por su atencion y/o ayuda tengo la siguiente duda
por consola hago un telnet 200.74.146.84 8600 y se coencta.
luego escribo la M y eneter
y me aparece un emnsaje
Deseo hacer esto por socket escribi el sigueitne codigo
$conexion = fsockopen (“200.74.146.84″, 8600);
if ($conexion) {
echo “Conexion realiaza con éxito”;
fwrite($conexion, “MARCHIV270223.9999.23OJO.1.98663305.escobar\n”);
echo fread($conexion, 1000).”-”;
fclose ($conexion);
se coencta bien pero a la hora de escribir o leer algo se demora 120 segundos y no muestra nada,
otra cosa esto solo funciona desde el pc dodne trabjo pues para hacer esto existe un vpn entre dos redes
sera que me podrian colaborar o ilustrar como podria hacer esto
mil gracias
Una pregunta importante…
solo he programado software offline, y estoy aprendiento programacion web, comprendo el codigo pero tengo una pregunta basica
donde meto el archivo de cliente y donde meto el del servidor??
estoy usando wamp como servidor local
Hola… estoy teniendo problemas con socket_create ya que me esta devolviendo “Warning: socket_create() Unable to create socket [1]: Operation not permitted” . No he podido encontrar en ningun lado una rta que indique a que se debe y como solucionarlo.
He intentado con fsockopen pero me devuelve “fsockopen() [function.fsockopen]: unable to connect to”…
Si alguien lidio ya con esto y sabe como solucionarlo, les agradecer mucho.
Saludos!
en que parte del servidor tengo que escribir el codigo server para poder abrirlo desde un telnet???
Hola,
Mucho gusto, magnifico foro, felicitaciones.
Necesito algo de ayuda con esto:
Tengo la necesidad de enviarle un estado a una aplicacion cliente (web) pero sin necesidad de que sea echa por una peticion del cliente, me explico:
1. Pongamos como ejemplo que necesito hacer una aplicacion (web) para monitorear el estado de una maquina.
2. la aplicacion digamos que es una pagina que me muestra un aviso con fondo verde si el estado de la maquina es activo.
——————
|ESTADO: ACTIVA|
——————
3. supongamos que la aplicacion se conecta a un servidor web Apache con PHP, lo mas normal. Y la maquina tiene alguna interfaz conectada por algun puerto al servidor y a traves de esta envia su estado al servidor. (esto lo hacen los electronicos, no recuerdo como se llama ¿¿¿PL???)
4. si la maquina se detiene, envia al servidor el cambio de estado, pasa de ACTIVA a DETENIDA (o 1 a 0)
5. cuando se da ese evento, el servidor (y PHP) deberia de enviarle es estado a la aplicacion cliente. (el cliente NO lo ha solicitado)
6. el cliente actualizaria su pantalla para mostrar
———————
|ESTADO: DETENIDA|
———————
PREGUNTA: Puedo pretender utilizar sockets para hacer esto???
Espero cordialmente que alguien pueda ayudarme o guiarme sobre que y por donde puedo buscar.
Cualquier colaboracion o idea de como hacerlo sera bienvenida.
Gracias a todos!!!
me urge…
NOTA: aclaro que necesito que el evento de enviarle los datos al cliente debe ser determinado por el servidor, solo y cuando el evento se realiza en la maquina por ejemplo. No me sirve que sea un SCRIPT del lado del cliente que este ejecutando una tarea de consultar el estado en el servidor cada cierto tiempo.
Es decir, el servidor debe saber a que cliente le envia la informacion.
Realmente muy bien explicado, codigo probado, y realmente funciona.
Ahora, tengo una duda, puede ejecutarse el servidor en un directorio personal de apache? es decir, en la universidad esta permitido el uso de sockets, pero la pregunta es, cuando se hace el socket_bind, se puede pasar como parametro el URL personal “host/~usuario/servidor.php” ?