PHP
Douilles
Recherche…
Socket client TCP
Création d'un socket utilisant le protocole TCP (Transmission Control Protocol)
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
Assurez-vous que le socket est créé avec succès. La fonction onSocketFailure
provient de l'exemple de manipulation des erreurs de socket dans cette rubrique.
if(!is_resource($socket)) onSocketFailure("Failed to create socket");
Connectez la prise à une adresse spécifiée
La deuxième ligne échoue normalement si la connexion échoue.
socket_connect($socket, "chat.stackoverflow.com", 6667)
or onSocketFailure("Failed to connect to chat.stackoverflow.com:6667", $socket);
Envoi de données au serveur
La fonction socket_write
envoie des octets via une socket. En PHP, un tableau d'octets est représenté par une chaîne, qui est normalement insensible au codage.
socket_write($socket, "NICK Alice\r\nUSER alice 0 * :Alice\r\n");
Recevoir des données du serveur
L'extrait suivant reçoit des données du serveur à l'aide de la fonction socket_read
.
Passer PHP_NORMAL_READ
comme troisième paramètre lit jusqu'à un octet \r
/ \n
, et cet octet est inclus dans la valeur de retour.
Passer PHP_BINARY_READ
, au contraire, lit la quantité de données requise à partir du flux.
Si socket_set_nonblock
été appelé auparavant et que PHP_BINARY_READ
est utilisé, socket_read
renverra false
immédiatement. Sinon, la méthode bloque jusqu'à ce que suffisamment de données (pour atteindre la longueur du deuxième paramètre ou pour terminer une ligne) soient reçues ou que le socket soit fermé.
Cet exemple lit les données d'un serveur supposé 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;
}
Fermer la prise
La fermeture du socket libère le socket et ses ressources associées.
socket_close($socket);
Socket serveur TCP
Création de socket
Créez un socket qui utilise le protocole TCP. C'est la même chose que la création d'un socket client.
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
Socket binding
Lier les connexions d'un réseau donné (paramètre 2) pour un port spécifique (paramètre 3) à la prise.
Le deuxième paramètre est généralement "0.0.0.0"
, qui accepte la connexion de tous les réseaux. Ça peut aussi
Une cause commune des erreurs de socket_bind
est que l'adresse spécifiée est déjà liée à un autre processus . Les autres processus sont généralement supprimés (généralement manuellement pour éviter de tuer accidentellement des processus critiques) afin que les sockets soient libérés.
socket_bind($socket, "0.0.0.0", 6667) or onSocketFailure("Failed to bind to 0.0.0.0:6667");
Mettre une prise à l'écoute
Faites en socket_listen
le socket écoute les connexions entrantes en utilisant socket_listen
. Le second paramètre est le nombre maximal de connexions permettant la mise en file d'attente avant leur acceptation.
socket_listen($socket, 5);
Connexion de manutention
Un serveur TCP est en réalité un serveur qui gère les connexions enfants. socket_accept
crée une nouvelle connexion enfant.
$conn = socket_accept($socket);
Le transfert de données pour une connexion à partir de socket_accept
est le même que pour un socket client TCP .
Lorsque cette connexion doit être fermée, appelez socket_close($conn);
directement. Cela n'affectera pas le socket du serveur TCP d'origine.
Fermer le serveur
En revanche, socket_close($socket);
devrait être appelé lorsque le serveur n'est plus utilisé. Cela libérera également l'adresse TCP, permettant aux autres processus de se lier à l'adresse.
Gestion des erreurs de socket
socket_last_error
peut être utilisé pour obtenir l'ID d'erreur de la dernière erreur provenant de l'extension sockets.
socket_strerror
peut être utilisé pour convertir l'ID en chaînes lisibles par l'homme.
function onSocketFailure(string $message, $socket = null) {
if(is_resource($socket)) {
$message .= ": " . socket_strerror(socket_last_error($socket));
}
die($message);
}
Socket serveur UDP
Un serveur UDP (User Datagram Protocol), contrairement à TCP, n'est pas basé sur les flux. Il est basé sur des paquets, c'est-à-dire qu'un client envoie des données dans des unités appelées "paquets" au serveur, et le client identifie les clients par leur adresse. Il n'y a pas de fonction intégrée qui relie les différents paquets envoyés par le même client (contrairement à TCP, où les données du même client sont gérées par une ressource spécifique créée par socket_accept
). On peut penser qu’une nouvelle connexion TCP est acceptée et fermée chaque fois qu’un paquet UDP arrive.
Création d'un socket de serveur UDP
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
Relier un socket à une adresse
Les paramètres sont les mêmes que pour un serveur TCP.
socket_bind($socket, "0.0.0.0", 9000) or onSocketFailure("Failed to bind to 0.0.0.0:9000", $socket);
Envoi d'un paquet
Cette ligne envoie $data
dans un paquet UDP à $address
: $port
.
socket_sendto($socket, $data, strlen($data), 0, $address, $port);
Recevoir un paquet
L'extrait de code suivant tente de gérer les paquets UDP de manière indexée par le client.
$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);
}
Fermer le serveur
socket_close
peut être utilisé sur la ressource de socket du serveur UDP. Cela libère l'adresse UDP, permettant aux autres processus de se lier à cette adresse.