In der PHP -Netzwerkprogrammierung wird die Funktion stream_socket_shutdown verwendet, um eine bestimmte Richtung (lesen, schreiben oder beides) einer Socket -Verbindung zu schließen. In der tatsächlichen Verwendung stoßen viele Entwickler jedoch auf Probleme wie abnormale Verbindungsunterbrechungen, Clientfehler und sogar Datenverlust nach dem Aufrufen von Stream_Socket_Shutdown . In diesem Artikel wird der Arbeitsmechanismus von stream_socket_shutdown eingehend analysiert, die Ursachen für Verbindungsausnahmen untersucht und Methoden zur Vermeidung und Reparatur angeben.
Die Funktionsdefinition von stream_socket_shutdown lautet wie folgt:
bool stream_socket_shutdown(resource $stream, int $how)
$ stream : Eine offene Socket -Stream -Ressource.
$ Wie : Schließen Sie die Richtung, nehmen Sie den Wert an:
Stream_shut_rd (0) Schließen Sie die Lesrichtung
Stream_shut_wr (1) Schließen Sie die Schreibrichtung
Stream_Shut_RDWR (2) Deaktivieren und Schreiben von Anweisungen ausschalten und schreiben
Zum Beispiel:
$socket = stream_socket_client("tcp://m66.net:8080", $errno, $errstr, 30);
if (!$socket) {
die("Verbindung ist fehlgeschlagen: $errstr ($errno)");
}
// Schließen Sie die Schreibrichtung,Gibt an, dass Daten nicht mehr gesendet werden
stream_socket_shutdown($socket, STREAM_SHUT_WR);
Nach dem Aufrufen von Stream_Socket_Shutdown wird eine bestimmte Richtung der Sockel geschlossen, und der Kernel sendet Flossenpakete an den Peer, was angibt, dass die Verbindung geschlossen ist.
Die Root -Ursache der Ausnahme ist, dass der Client oder Server bei Verwendung von Stream_Socket_Shutdown das Shutdown -Signal der Verbindung nicht ordnungsgemäß verarbeitet oder die Schließreihenfolge unangemessen ist. Speziell manifestiert als:
Schließen Sie die Schreibrichtung im Voraus , wodurch die Verbindung getrennt wird, wenn der Peer die Daten nicht beendet.
Gleichzeitig wird die Les- und Schreibrichtung ausgeschaltet , die Daten werden jedoch nicht gelesen, was zu Datenverlust führt.
Nach dem Schließen der Schreibrichtung werden die verbleibenden Daten nicht rechtzeitig gelesen , was zu einer abnormalen Verbindung führt.
Das Flossenpaket wird nicht vom Peer verarbeitet, was die Verbindung zu Zeitüberschreitungen und Trennung verursacht .
Diese Probleme sind besonders anfällig für TCP-Long-Verbindung oder Kommunikationsszenarien mit Halbduplex.
Wenn Sie nur die Daten senden und nicht vorhaben, sie noch einmal zu schreiben, rufen Sie an:
stream_socket_shutdown($socket, STREAM_SHUT_WR);
Dies bedeutet, dass die Schreibrichtung geschlossen ist, aber die Leserrichtung bleibt immer noch aufbewahrt und wartet auf die vom Gleichaltrigen gesendeten Daten.
Wenn sowohl der Server als auch der Client zuerst die Schreibrichtung ausschalten müssen, stellen Sie sicher, dass der Peer genügend Zeit hat, um die verbleibenden Daten zu lesen.
Nach dem Schließen der Schreibrichtung kann die Verbindung die Daten weiterhin lesen. Der allgemeine Ansatz ist:
// Schließen Sie die Schreibrichtung
stream_socket_shutdown($socket, STREAM_SHUT_WR);
// Lesen Sie weiterhin Peer -Daten, bisEOF
while (!feof($socket)) {
$data = fread($socket, 8192);
if ($data === false) {
break;
}
// Verarbeitungsdaten
}
Stellen Sie sicher, dass keine Legacy -Daten nicht gelesen werden.
Schließen Sie zunächst die Schreibrichtung und benachrichtigen Sie die zugesandten Peer -Daten.
Lesen Sie die Daten, die der Peer zurückgeben kann.
Schließen Sie nach dem Lesen die Lesrichtung oder schließen Sie die gesamte Verbindung.
Verwenden Sie Stream_Set_Timeout , um das Lese- und Schreiben von Timeout festzulegen, um das Blockieren von Verknüpfungshängen zu vermeiden.
Das folgende Beispiel zeigt den richtigen Weg, um eine sichere Verbindung auf den Server zu schreiben:
$server = stream_socket_server("tcp://0.0.0.0:12345", $errno, $errstr);
if (!$server) {
die("Den Server kann nicht gestartet werden: $errstr ($errno)");
}
$client = stream_socket_accept($server);
if ($client) {
// Antwortdaten senden
fwrite($client, "Hello from server\n");
// Schließen Sie die Schreibrichtung,Benachrichtigen Sie den Client, dass es keine Daten mehr gibt
stream_socket_shutdown($client, STREAM_SHUT_WR);
// Lesen Sie die vom Client gesendeten Daten fort
while (!feof($client)) {
$data = fread($client, 8192);
if ($data === false || $data === "") {
break;
}
echo "Empfangene Clientdaten: $data\n";
}
// Schließen Sie die Verbindung
fclose($client);
}
fclose($server);
Vermeiden Sie es, das Lesen und schreiben Sie gleichzeitig Anweisungen aus, es sei denn, es ist sicher, dass die Kommunikation nicht mehr durchgeführt wird.
Vermeiden Sie für lange Verbindungen häufige Aufrufe bei Stream_Socket_Shutdown und verwenden Sie Herzschlagpakete und Timeout -Erkennung vernünftigerweise.
Stellen Sie sicher, dass das Protokolldesign des Clients und des Servers klar über das Timing und die Reihenfolge der Verbindungsschließung ist.
Verwenden Sie Stream_Set_Blocking und Stream_Set_Timeout, um das Blockieren zu verhindern.
stream_socket_shutdown ist ein wichtiges Werkzeug zum Schließen von Socket -Verbindungen, aber unangemessene Verwendung kann leicht zu abnormalen Verbindungsunterbrechungen führen. Das Verständnis der Semantik der Schließung, der vernünftigen Auswahl der Schlussrichtung und der Sicherstellung der Les- und Schreibreihenfolge der Daten nach dem Schließen ist der Schlüssel zur Vermeidung und Behebung von Problemen. Durch die Kombination der korrekten Zeitüberschreitungseinstellungen und Ausnahmebehandlung können PHP -Netzwerkprogramme stabiler und zuverlässiger werden.