◆ Socket-Grundlagen
PHP verwendet die Socket-Bibliothek von Berkley, um seine Verbindungen herzustellen. Ein Socket ist nichts anderes als eine Datenstruktur. Sie verwenden diese Socket-Datenstruktur, um eine Sitzung zwischen dem Client und dem Server zu starten. Dieser Server hört ständig zu und bereitet sich auf die Generierung einer neuen Sitzung vor. Wenn ein Client eine Verbindung zum Server herstellt, öffnet er einen Port, auf dem der Server auf eine Sitzung wartet. Zu diesem Zeitpunkt akzeptiert der Server die Verbindungsanforderung des Clients und führt dann einen Zyklus durch. Jetzt kann der Client Informationen an den Server senden, und der Server kann Informationen an den Client senden.
Um einen Socket zu generieren, benötigen Sie drei Variablen: ein Protokoll, einen Socket-Typ und einen öffentlichen Protokolltyp. Beim Generieren eines Sockets stehen drei Protokolle zur Auswahl. Lesen Sie weiter unten, um detaillierte Protokollinhalte zu erhalten.
Die Definition eines öffentlichen Protokolltyps ist ein wesentliches Element der Verbindung. In der folgenden Tabelle werfen wir einen Blick auf die gängigen Protokolltypen.
Tabelle 1: Protokollname/Konstantenbeschreibung
AF_INET Dies ist das von den meisten Sockets verwendete Protokoll, das TCP oder UDP zur Übertragung verwendet und in IPv4-Adressen verwendet wird.
AF_INET6 ähnelt dem oben genannten, wird jedoch für IPv6-Adressen verwendet.
Lokales AF_UNIX-Protokoll, das auf Unix- und Linux-Systemen verwendet wird. Es wird normalerweise verwendet, wenn sich Client und Server auf demselben Computer befinden
SOCK_STREAM Dieses Protokoll ist eine sequentielle, zuverlässige, datenintegrierte Bytestream-basierte Verbindung. Dies ist der am häufigsten verwendete Socket-Typ. Dieser Socket verwendet TCP für die Übertragung.
SOCK_DGRAM Dieses Protokoll ist ein verbindungsloser Übertragungsaufruf mit fester Länge. Dieses Protokoll ist unzuverlässig und verwendet UDP für seine Verbindungen.
SOCK_SEQPACKET Bei diesem Protokoll handelt es sich um eine zuverlässige Zweileitungsverbindung, die Datenpakete fester Länge zur Übertragung sendet. Dieses Paket muss vollständig akzeptiert werden, bevor es gelesen werden kann.
SOCK_RAW Dieser Socket-Typ bietet Einzelnetzwerkzugriff. Dieser Socket-Typ verwendet das öffentliche ICMP-Protokoll. (Ping und Traceroute verwenden dieses Protokoll)
SOCK_RDM Dieser Typ wird selten verwendet und ist auf den meisten Betriebssystemen nicht implementiert. Er ist für die Verwendung durch die Datenverbindungsschicht vorgesehen und garantiert nicht die Paketreihenfolge
ICMP Internet Control Message Protocol, wird hauptsächlich auf Gateways und Hosts verwendet, um Netzwerkbedingungen zu überprüfen und Fehlermeldungen zu melden
UDP User Datagram Protocol, ein verbindungsloses und unzuverlässiges Übertragungsprotokoll
Das TCP Transmission Control Protocol, das am häufigsten verwendete zuverlässige öffentliche Protokoll, kann sicherstellen, dass das Datenpaket den Empfänger erreichen kann. Wenn während des Übertragungsprozesses ein Fehler auftritt, wird das Fehlerpaket erneut gesendet.
Nachdem Sie nun die drei Elemente kennen, die einen Socket generieren, verwenden wir die Funktion socket_create() in PHP, um einen Socket zu generieren. Diese socket_create()-Funktion erfordert drei Parameter: ein Protokoll, einen Socket-Typ und ein öffentliches Protokoll. Die Funktion socket_create() gibt einen Ressourcentyp zurück, der den Socket enthält, wenn sie erfolgreich ausgeführt wird. Wenn sie fehlschlägt, gibt sie false zurück.
Ressource socket_create(int Protocol, int socketType, int commonProtocol);
Jetzt erstellen Sie einen Socket, was dann? PHP bietet mehrere Funktionen zur Manipulation von Sockets. Sie können einen Socket an eine IP binden, die Kommunikation eines Sockets abhören und einen Socket akzeptieren. Schauen wir uns nun ein Beispiel an, um zu verstehen, wie die Funktion einen Socket generiert, akzeptiert und abhört.
<?php
$commonProtocol = getprotobyname("tcp");//Verwenden Sie den öffentlichen Protokollnamen, um einen Protokolltyp abzurufen
$socket = socket_create(AF_INET, SOCK_STREAM, $commonProtocol);//Generieren Sie einen Socket und geben Sie eine Instanz der Socket-Ressource zurück
socket_bind($socket, 'localhost', 1337);//Socket an lokalen Computer binden
socket_listen($socket);//Alle eingehenden Socket-Verbindungen abhören
// Weitere Socket-Funktionalität folgt
?>
Das obige Beispiel generiert Ihre eigene Serverseite. Die erste Zeile des Beispiels,
$commonProtocol = getprotobyname("tcp");
Verwenden Sie den öffentlichen Protokollnamen, um einen Protokolltyp abzurufen. Hier wird das öffentliche TCP-Protokoll verwendet. Wenn Sie das UDP- oder ICMP-Protokoll verwenden möchten, sollten Sie die Parameter der Funktion getprotobyname() auf „udp“ oder „icmp“ ändern. Eine andere Alternative besteht darin, SOL_TCP oder SOL_UDP in der Funktion socket_create() anzugeben, anstatt die Funktion getprotobyname() zu verwenden.
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
Die zweite Zeile des Beispiels erstellt einen Socket und gibt eine Instanz der Socket-Ressource zurück. Nachdem Sie über eine Instanz der Socket-Ressource verfügen, müssen Sie den Socket an eine IP-Adresse und einen Port binden.
socket_bind($socket, 'localhost', 1337);
Hier binden Sie den Socket an den lokalen Computer (127.0.0.1) und binden den Socket an Ihren 1337-Port. Dann müssen Sie auf alle eingehenden Socket-Verbindungen warten.
socket_listen($socket);
Nach der vierten Zeile müssen Sie alle Socket-Funktionen und deren Verwendung verstehen.
Tabelle 4: Beschreibung des Funktionsnamens der Socket-Funktion
socket_accept() akzeptiert eine Socket-Verbindung
socket_bind() bindet den Socket an eine IP-Adresse und einen Port
socket_clear_error() löscht den Socket-Fehler oder den letzten Fehlercode
socket_close() schließt eine Socket-Ressource
socket_connect() startet eine Socket-Verbindung
socket_create_listen() öffnet einen Socket, der den angegebenen Port überwacht
socket_create_pair() generiert ein Paar nicht unterscheidbarer Sockets in einem Array
socket_create() generiert einen Socket, was dem Generieren einer Socket-Datenstruktur entspricht
socket_get_option() Socket-Optionen abrufen
socket_getpeername() Ruft die IP-Adresse eines entfernten ähnlichen Hosts ab
socket_getsockname() ruft die IP-Adresse des lokalen Sockets ab
socket_iovec_add() fügt einem Scatter/Aggregate-Array einen neuen Vektor hinzu
socket_iovec_alloc() Diese Funktion erstellt eine iovec-Datenstruktur, die senden, empfangen, lesen und schreiben kann
socket_iovec_delete() löscht einen zugewiesenen Iovec
socket_iovec_fetch() gibt die Daten der angegebenen iovec-Ressource zurück
socket_iovec_free() gibt eine iovec-Ressource frei
socket_iovec_set() legt den neuen Wert der iovec-Daten fest
socket_last_error() ruft den letzten Fehlercode des aktuellen Sockets ab
socket_listen() lauscht auf alle Verbindungen vom angegebenen Socket
socket_read() liest Daten der angegebenen Länge
socket_readv() liest Daten aus dem Scatter/Aggregate-Array
socket_recv() beendet die Daten vom Socket zum Cache
socket_recvfrom() akzeptiert Daten vom angegebenen Socket. Wenn nicht angegeben, wird standardmäßig der aktuelle Socket verwendet.
socket_recvmsg() empfängt Nachrichten von iovec
socket_select() Mehrfachauswahl
socket_send() Diese Funktion sendet Daten an den verbundenen Socket
socket_sendmsg() sendet eine Nachricht an den Socket
socket_sendto() sendet eine Nachricht an den Socket an der angegebenen Adresse
socket_set_block() setzt den Socket in den Blockmodus
socket_set_nonblock() Setzt den Socket auf den Nicht-Block-Modus
socket_set_option() legt Socket-Optionen fest
socket_shutdown() Mit dieser Funktion können Sie den angegebenen Socket beim Lesen, Schreiben oder Schließen schließen
socket_strerror() gibt den detaillierten Fehler mit der angegebenen Fehlernummer zurück
socket_write() schreibt Daten in den Socket-Cache
socket_writev() schreibt Daten in verstreute/aggregierte Arrays. Um diese Funktionen zu verwenden, müssen Sie Ihre php.ini-Datei öffnen und entfernen Folgender Kommentar vor dieser Zeile:
extension=php_sockets.dll
Wenn Sie den Kommentar nicht entfernen können, verwenden Sie den folgenden Code, um die Erweiterungsbibliothek zu laden:
<?php
if(!extension_loaded('sockets')) {
if(strtoupper(substr(PHP_OS, 3)) == „WIN“) {
dl('php_sockets.dll');
}anders{
dl('sockets.so');
}
}
?>
Wenn Sie nicht wissen, ob Ihr Socket geöffnet ist, können Sie mit der Funktion phpinfo() feststellen, ob der Socket geöffnet ist. Sie können überprüfen, ob der Socket geöffnet ist, indem Sie die PHPInfo-Informationen überprüfen.
Sehen Sie sich die Informationen von phpinfo() zum Socket an. ◆ Erzeugen Sie einen Server. Lassen Sie uns nun das erste Beispiel verbessern. Sie müssen einen bestimmten Socket abhören und Benutzerverbindungen verarbeiten.
<?php
$commonProtocol = getprotobyname("tcp");
$socket = socket_create(AF_INET, SOCK_STREAM, $commonProtocol);
socket_bind($socket, 'localhost', 1337);
socket_listen($socket);
//Akzeptiere alle eingehenden Verbindungen zum Server
$connection = socket_accept($socket);
if($connection){
socket_write($connection, „Sie haben eine Verbindung zum Socket hergestellt...nr“);
}
?>
Sie sollten Ihre Eingabeaufforderung verwenden, um dieses Beispiel auszuführen. Der Grund dafür ist, dass hier ein Server und keine Webseite generiert wird. Wenn Sie versuchen, dieses Skript mit einem Webbrowser auszuführen, besteht eine gute Chance, dass die 30-Sekunden-Grenze überschritten wird. Sie können den folgenden Code verwenden, um eine unendliche Laufzeit festzulegen. Es wird jedoch empfohlen, zum Ausführen die Eingabeaufforderung zu verwenden.
set_time_limit(0);
Testen Sie einfach dieses Skript in Ihrer Eingabeaufforderung:
PHP.exe example01_server.php
Wenn Sie den Pfad zum PHP-Interpreter nicht in den Umgebungsvariablen Ihres Systems festgelegt haben, müssen Sie den Pfad zu php.exe angeben. Wenn Sie den Server ausführen, können Sie ihn testen, indem Sie über Telnet eine Verbindung zu Port 1337 herstellen.
Es gibt drei Probleme mit der Serverseite oben: 1. Sie kann nicht mehrere Verbindungen akzeptieren. 2. Es wird nur ein Befehl ausgeführt. 3. Sie können keine Verbindung zu diesem Server über einen Webbrowser herstellen.
Dieses erste Problem ist einfacher zu lösen: Sie können jedes Mal eine Anwendung verwenden, um eine Verbindung zum Server herzustellen. Das nächste Problem besteht jedoch darin, dass Sie eine Webseite verwenden müssen, um eine Verbindung zum Server herzustellen, was schwieriger ist. Sie können Ihren Server veranlassen, die Verbindung anzunehmen, einige Daten an den Client zu schreiben (falls er diese schreiben muss), die Verbindung schließen und auf die nächste Verbindung warten.
Verbessern Sie den vorherigen Code und generieren Sie den folgenden Code, um Ihren neuen Server zu erstellen:
<?php
// Richten Sie unseren Socket ein
$commonProtocol = getprotobyname("tcp");
$socket = socket_create(AF_INET, SOCK_STREAM, $commonProtocol);
socket_bind($socket, 'localhost', 1337); //socket_bind() bindet den Socket an eine IP-Adresse und einen Port
socket_listen($socket);
//Initialisiere den Puffer
$buffer = "KEINE DATEN";
while(true) {
// Alle auf diesem Socket eingehenden Verbindungen akzeptieren
$connection = socket_accept($socket);//socket_accept() akzeptiert eine Socket-Verbindung
printf("Socket verbundenrn");
// Überprüfen Sie, ob sich etwas im Puffer befindet
if($buffer != ""){
printf("Etwas ist im Puffer...Daten werden gesendet...rn");
socket_write($connection, $buffer . "rn"); //socket_write() schreibt Daten in den Socket-Cache
printf("In Socket geschriebenrn");
}anders {
printf("Keine Daten im Pufferrn");
}
//Die Eingabe abrufen
while($data = socket_read($connection, 1024, PHP_NORMAL_READ))//socket_read() liest Daten der angegebenen Länge
{
$buffer = $data;
socket_write($connection, "Informationen empfangenrn");
printf("Puffer: " . $buffer . "rn");
}
socket_close($connection); //socket_close() schließt eine Socket-Ressource
printf("Socket geschlossenrnrn");
}
?>
Was soll dieser Server tun? Es initialisiert einen Socket und öffnet einen Cache zum Senden und Empfangen von Daten. Es wartet auf eine Verbindung und sobald eine Verbindung hergestellt ist, wird auf dem Bildschirm auf der Serverseite „Socket connected“ angezeigt. Dieser Server überprüft den Puffer und sendet die Daten an den angeschlossenen Computer, wenn sich Daten im Puffer befinden. Anschließend sendet es eine Annahmenachricht für diese Daten. Sobald es die Nachricht akzeptiert, speichert es die Nachricht in den Daten, macht den angeschlossenen Computer auf die Nachricht aufmerksam und schließt schließlich die Verbindung. Wenn die Verbindung geschlossen wird, beginnt der Server mit der Verarbeitung der nächsten Verbindung.
◆ Es ist einfach, einen Client zur Lösung des zweiten Problems zu generieren. Sie müssen eine PHP-Seite erstellen, eine Verbindung zu einem Socket herstellen, einige Daten an den Cache senden und diese verarbeiten. Dann warten die verarbeiteten Daten auf Sie und Sie können Ihre Daten an den Server senden. Bei einer anderen Clientverbindung werden diese Daten verarbeitet.
Das folgende Beispiel demonstriert die Verwendung von Sockets:
<?php
// Den Socket erstellen und verbinden
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
$connection = socket_connect($socket,'localhost', 1337);
while($buffer = socket_read($socket, 1024, PHP_NORMAL_READ)) {
if($buffer == "NO DATA") {
echo(“<p>KEINE DATEN</p>”);
brechen;
}anders{
// Etwas mit den Daten im Puffer machen
echo(“<p>Pufferdaten: „ . $buffer . „</p>“);
}
}
echo(“<p>In Socket schreiben</p>”);
// Einige Testdaten in unseren Socket schreiben
if(!socket_write($socket, „EINIGE DATENrn“)){
echo(“<p>Schreiben fehlgeschlagen</p>“);
}
// Lies jede Antwort vom Socket
while($buffer = socket_read($socket, 1024, PHP_NORMAL_READ)){
echo(“<p>Gesendete Daten waren: EINIGE DATEN<br> Antwort war:“ . $buffer . „</p>“);
}
echo(“<p>Fertig Lesen aus Socket</p>“);
?>
Dieser Beispielcode zeigt, wie der Client eine Verbindung zum Server herstellt. Der Client liest die Daten. Wenn dies die erste Verbindung ist, die in diesem Zyklus eintrifft, sendet der Server „KEINE DATEN“ an den Client zurück. In diesem Fall befindet sich der Client an der Spitze der Verbindung. Der Client sendet seine Daten an den Server, die Daten werden an den Server gesendet und der Client wartet auf eine Antwort. Sobald die Antwort empfangen wurde, wird die Antwort auf den Bildschirm geschrieben.