PHP
Enchufes
Buscar..
Socket cliente TCP
Creando un socket que usa el TCP (Protocolo de Control de Transmisión)
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
Asegúrese de que el zócalo se haya creado correctamente. La función onSocketFailure
proviene del ejemplo Manejo de errores de socket en este tema.
if(!is_resource($socket)) onSocketFailure("Failed to create socket");
Conecte el zócalo a una dirección especificada
La segunda línea falla con gracia si falla la conexión.
socket_connect($socket, "chat.stackoverflow.com", 6667)
or onSocketFailure("Failed to connect to chat.stackoverflow.com:6667", $socket);
Enviando datos al servidor
La función socket_write
envía bytes a través de un socket. En PHP, una matriz de bytes está representada por una cadena, que normalmente es insensible a la codificación.
socket_write($socket, "NICK Alice\r\nUSER alice 0 * :Alice\r\n");
Recibiendo datos del servidor
El siguiente fragmento de socket_read
recibe algunos datos del servidor mediante la función socket_read
.
Al pasar PHP_NORMAL_READ
como el tercer parámetro se lee hasta un byte \r
/ \n
, y este byte se incluye en el valor de retorno.
Al pasar PHP_BINARY_READ
, por el contrario, lee la cantidad requerida de datos de la secuencia.
Si socket_set_nonblock
fue llamado antes, y PHP_BINARY_READ
se utiliza, socket_read
volverá false
inmediatamente. De lo contrario, el método se bloquea hasta que se reciben suficientes datos (para alcanzar la longitud en el segundo parámetro, o para alcanzar un final de línea), o se cierra el zócalo.
Este ejemplo lee datos de un servidor supuestamente IRC.
while(true) {
// read a line from the socket
$line = socket_read($socket, 1024, PHP_NORMAL_READ);
if(substr($line, -1) === "\r") {
// read/skip one byte from the socket
// we assume that the next byte in the stream must be a \n.
// this is actually bad in practice; the script is vulnerable to unexpected values
socket_read($socket, 1, PHP_BINARY_READ);
}
$message = parseLine($line);
if($message->type === "QUIT") break;
}
Cerrando el zócalo
Cerrar el socket libera el socket y sus recursos asociados.
socket_close($socket);
Zócalo del servidor TCP
Creación de zócalo
Crea un socket que use el TCP. Es lo mismo que crear un socket de cliente.
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
Enlace de zócalo
Enlace las conexiones de una red dada (parámetro 2) para un puerto específico (parámetro 3) al socket.
El segundo parámetro suele ser "0.0.0.0"
, que acepta la conexión de todas las redes. También puede
Una causa común de errores de socket_bind
es que la dirección especificada ya está vinculada a otro proceso . Otros procesos generalmente se eliminan (generalmente de forma manual para evitar la muerte accidental de procesos críticos) para que los sockets se liberen.
socket_bind($socket, "0.0.0.0", 6667) or onSocketFailure("Failed to bind to 0.0.0.0:6667");
Establecer un zócalo para escuchar.
Haz que el socket escuche las conexiones entrantes usando socket_listen
. El segundo parámetro es el número máximo de conexiones para permitir la puesta en cola antes de que sean aceptadas.
socket_listen($socket, 5);
Manejo de conexion
Un servidor TCP es en realidad un servidor que maneja conexiones secundarias. socket_accept
crea una nueva conexión secundaria.
$conn = socket_accept($socket);
La transferencia de datos para una conexión desde socket_accept
es la misma que para un socket de cliente TCP .
Cuando se debe cerrar esta conexión, llame a socket_close($conn);
directamente. Esto no afectará el socket del servidor TCP original.
Cerrando el servidor
Por otro lado, socket_close($socket);
debe llamarse cuando el servidor ya no se utiliza. Esto también liberará la dirección TCP, permitiendo que otros procesos se unan a la dirección.
Manejo de errores de socket
socket_last_error
se puede usar para obtener el ID de error del último error de la extensión de sockets.
socket_strerror
se puede usar para convertir el ID en cadenas legibles para el usuario.
function onSocketFailure(string $message, $socket = null) {
if(is_resource($socket)) {
$message .= ": " . socket_strerror(socket_last_error($socket));
}
die($message);
}
Servidor UDP socket
Un servidor UDP (protocolo de datagramas de usuario), a diferencia de TCP, no está basado en flujo. Se basa en paquetes, es decir, un cliente envía datos en unidades denominadas "paquetes" al servidor, y el cliente identifica a los clientes por su dirección. No hay una función incorporada que relacione diferentes paquetes enviados desde el mismo cliente (a diferencia de TCP, donde los datos del mismo cliente son manejados por un recurso específico creado por socket_accept
). Puede pensarse como una nueva conexión TCP es aceptada y cerrada cada vez que llega un paquete UDP.
Creando un socket de servidor UDP
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
Atar un socket a una dirección
Los parámetros son los mismos que para un servidor TCP.
socket_bind($socket, "0.0.0.0", 9000) or onSocketFailure("Failed to bind to 0.0.0.0:9000", $socket);
Enviando un paquete
Esta línea envía $data
en un paquete UDP a $address
: $port
.
socket_sendto($socket, $data, strlen($data), 0, $address, $port);
Recibiendo un paquete
El siguiente fragmento de código intenta administrar paquetes UDP de una manera indexada por el cliente.
$clients = [];
while (true){
socket_recvfrom($socket, $buffer, 32768, 0, $ip, $port) === true
or onSocketFailure("Failed to receive packet", $socket);
$address = "$ip:$port";
if (!isset($clients[$address])) $clients[$address] = new Client();
$clients[$address]->handlePacket($buffer);
}
Cerrando el servidor
socket_close
se puede utilizar en el recurso de socket del servidor UDP. Esto liberará la dirección UDP, permitiendo que otros procesos se unan a esta dirección.