PHP
Steckdosen
Suche…
TCP-Client-Socket
Socket erstellen, der das TCP (Transmission Control Protocol) verwendet
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
Stellen Sie sicher, dass der Socket erfolgreich erstellt wurde. Die onSocketFailure
Funktion stammt aus dem Beispiel zur Behandlung von onSocketFailure
in diesem Thema.
if(!is_resource($socket)) onSocketFailure("Failed to create socket");
Verbinden Sie den Sockel mit einer angegebenen Adresse
Die zweite Zeile schlägt fehl, wenn die Verbindung fehlgeschlagen ist.
socket_connect($socket, "chat.stackoverflow.com", 6667)
or onSocketFailure("Failed to connect to chat.stackoverflow.com:6667", $socket);
Daten an den Server senden
Die Funktion socket_write
sendet Bytes über einen Socket. In PHP wird ein Byte-Array durch eine Zeichenfolge dargestellt, die normalerweise für die Codierung unempfindlich ist.
socket_write($socket, "NICK Alice\r\nUSER alice 0 * :Alice\r\n");
Daten vom Server empfangen
Das folgende Snippet empfängt einige Daten vom Server mithilfe der Funktion socket_read
.
Das Übergeben von PHP_NORMAL_READ
als dritten Parameter liest bis zu einem \r
/ \n
Byte. Dieses Byte ist im Rückgabewert enthalten.
Das Übergeben von PHP_BINARY_READ
liest die erforderliche Datenmenge aus dem Stream.
Wenn socket_set_nonblock
aufgerufen wurde und PHP_BINARY_READ
verwendet wird, gibt socket_read
sofort false
. Ansonsten blockiert die Methode, bis genügend Daten (um die Länge im zweiten Parameter zu erreichen oder ein Zeilenende zu erreichen) empfangen werden oder der Socket geschlossen ist.
In diesem Beispiel werden Daten von einem vermeintlichen IRC-Server gelesen.
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;
}
Steckdose schließen
Durch das Schließen des Sockets werden der Socket und die zugehörigen Ressourcen freigegeben.
socket_close($socket);
TCP-Server-Socket
Socket-Erstellung
Erstellen Sie einen Socket, der das TCP verwendet. Es ist das gleiche wie das Erstellen eines Client-Sockets.
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
Socket-Bindung
Binden Sie Verbindungen von einem bestimmten Netzwerk (Parameter 2) für einen bestimmten Port (Parameter 3) an den Socket.
Der zweite Parameter ist normalerweise "0.0.0.0"
, wodurch Verbindungen von allen Netzwerken akzeptiert werden. Es kann auch
Eine häufige Fehlerursache von socket_bind
besteht darin, dass die angegebene Adresse bereits an einen anderen Prozess gebunden ist . Andere Prozesse werden normalerweise abgebrochen (normalerweise manuell, um zu verhindern, dass kritische Prozesse versehentlich abgebrochen werden), so dass die Steckdosen freigegeben werden.
socket_bind($socket, "0.0.0.0", 6667) or onSocketFailure("Failed to bind to 0.0.0.0:6667");
Stellen Sie eine Steckdose für das Abhören ein
socket_listen
Sie den Socket eingehende Verbindungen mithilfe von socket_listen
. Der zweite Parameter ist die maximale Anzahl von Verbindungen, die das Einreihen in die Warteschlange zulassen, bevor diese akzeptiert werden.
socket_listen($socket, 5);
Verbindung handhaben
Ein TCP-Server ist eigentlich ein Server, der untergeordnete Verbindungen verarbeitet. socket_accept
erstellt eine neue socket_accept
Verbindung.
$conn = socket_accept($socket);
Die Datenübertragung für eine Verbindung von socket_accept
ist die gleiche wie für einen TCP-Client-Socket .
Wenn diese Verbindung geschlossen werden soll, rufen Sie socket_close($conn);
direkt. Dies hat keinen Einfluss auf den ursprünglichen TCP-Server-Socket.
Server schließen
Auf der anderen Seite socket_close($socket);
sollte aufgerufen werden, wenn der Server nicht mehr verwendet wird. Dadurch wird auch die TCP-Adresse freigegeben, sodass andere Prozesse an die Adresse binden können.
Behandlung von Socketfehlern
socket_last_error
kann verwendet werden, um die Fehler-ID des letzten Fehlers von der Sockets-Erweiterung socket_last_error
.
socket_strerror
kann die ID in vom Menschen lesbare Zeichenketten konvertiert werden.
function onSocketFailure(string $message, $socket = null) {
if(is_resource($socket)) {
$message .= ": " . socket_strerror(socket_last_error($socket));
}
die($message);
}
UDP-Server-Socket
Ein UDP-Server (User Datagram Protocol) ist im Gegensatz zu TCP nicht Stream-basiert. Es ist paketbasiert, dh ein Client sendet Daten in Einheiten, die "Pakete" genannt werden, an den Server, und der Client identifiziert Clients anhand ihrer Adresse. Es gibt keine integrierte Funktion, die verschiedene vom selben Client gesendete Pakete in Beziehung setzt (im Gegensatz zu TCP, bei dem Daten desselben Clients von einer bestimmten, von socket_accept
erstellten Ressource socket_accept
). Es kann angenommen werden, dass eine neue TCP-Verbindung jedes Mal akzeptiert und geschlossen wird, wenn ein UDP-Paket ankommt.
UDP-Server-Socket erstellen
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
Einen Socket an eine Adresse binden
Die Parameter sind die gleichen wie für einen TCP-Server.
socket_bind($socket, "0.0.0.0", 9000) or onSocketFailure("Failed to bind to 0.0.0.0:9000", $socket);
Paket senden
Diese Zeile sendet $data
in einem UDP-Paket an $address
: $port
.
socket_sendto($socket, $data, strlen($data), 0, $address, $port);
Ein Paket erhalten
Das folgende Snippet versucht, UDP-Pakete clientindiziert zu verwalten.
$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);
}
Server schließen
socket_close
kann für die UDP-Server-Socket-Ressource verwendet werden. Dadurch wird die UDP-Adresse freigegeben, sodass andere Prozesse an diese Adresse binden können.