PHP Handbuch
Zurück |  | Nach vorne

# XCVII. Socket Funktionen

# Einführung

Die Socket-Erweiterung stellt eine hardwarenahe Schnittstelle zu den Datenaustauschfunktionen über eine Socket-Verbindung zur Verfügung, die auf den bekannten BSD Sockets aufbaut, und bietet die Möglichkeit, entweder als Socket-Server oder als Client zu agieren.

Für eine allgemeinere clientseitige Socket Schnittstelle siehe fsockopen() und pfsockopen().

Wenn man diese Funktionen benutzt, darf man nicht vergessen, dass, obwohl viele der Funktionen gleichlautende Namen wie ihre Entsprechungen in C haben, sie dennoch oft unterschiedliche Deklarationen haben. Bitte lesen Sie die Deklarationen, um Verwirrung zu vermeiden.

Das heisst, wem Socketprogrammierung fremd ist, der findet eine grosse Menge nützlicher Materialien in den entsprechenden Unix manpages und es gibt jede Menge von Tutorials und Informationen über Socketprogrammierung in C im Internet. Vieles davon kann mit leichten Änderungen für die Socketprogrammierung mit PHP benutzt werden. Die UNIX Socket FAQ ist dafür ein guter Anfang.

Warnung
Diese Erweiterung ist EXPERIMENTELL. Das Verhalten dieser Erweiterung, einschließlich der Funktionsnamen, und alles Andere was hier dokumentiert ist, kann sich in zukünftigen PHP-Versionen ohne Ankündigung ändern. Seien Sie gewarnt und verwenden Sie diese Erweiterung auf eigenes Risiko.

# Anforderungen

Diese Erweiterung benötigt zur Erstellung keine externen Bibliotheken.

# Installation

Die hier beschriebenen Socket Funktionen sind Teil einer PHP Erweiterung, die beim Kompilieren mit der Option `--enable-sockets` beim Befehl configure eingebunden werden muss.

# Laufzeit Konfiguration

Diese Erweiterung definiert keine Konfigurationseinstellungen in der `php.ini`.

# Resource Typen

Diese Erweiterung definiert keine Resource-Typen.

# Vordefinierte Konstanten

Folgende Konstanten werden von dieser Erweiterung definiert und stehen nur zur Verfügung, wenn die Erweiterung entweder statisch in PHP kompiliert oder dynamisch zur Laufzeit geladen wurde.

`AF_UNIX` (integer)

`AF_INET` (integer)

`SOCK_STREAM` (integer)

`SOCK_DGRAM` (integer)

`SOCK_RAW` (integer)

`SOCK_SEQPACKET` (integer)

`SOCK_RDM` (integer)

`MSG_OOB` (integer)

`MSG_WAITALL` (integer)

`MSG_PEEK` (integer)

`MSG_DONTROUTE` (integer)

`SO_DEBUG` (integer)

`SO_REUSEADDR` (integer)

`SO_KEEPALIVE` (integer)

`SO_DONTROUTE` (integer)

`SO_LINGER` (integer)

`SO_BROADCAST` (integer)

`SO_OOBINLINE` (integer)

`SO_SNDBUF` (integer)

`SO_RCVBUF` (integer)

`SO_SNDLOWAT` (integer)

`SO_RCVLOWAT` (integer)

`SO_SNDTIMEO` (integer)

`SO_RCVTIMEO` (integer)

`SO_TYPE` (integer)

`SO_ERROR` (integer)

`SOL_SOCKET` (integer)

`PHP_NORMAL_READ` (integer)

`PHP_BINARY_READ` (integer)

`SOL_TCP` (integer)

`SOL_UDP` (integer)

# Socket Fehler

Die Socket-Erweiterung wurde geschrieben, um eine nützliche Schnittstelle zu den mächtigen BSD-Funktionen zur Verfügung zu stellen. Es wurde darauf geachtet, dass die Funktionen sowohl unter Win32 als auch unter Unix-Implementierungen arbeiten. Fast alle Socket-Funktionen können unter besonderen Umständen fehlschlagen und deshalb eine `E_WARNING`- Meldung ausgeben, die den aufgetretenen Fehler beschreibt. Dies ist manchmal nicht wünschenswert für den Entwickler. Zum Beispiel kann die Funktion socket_read() plötzlich eine `E_WARNING`-Meldung ausgeben, weil die Verbindung unerwartet beendet wurde. Normalerweise werden solche Meldungen mit dem `@`-Operator unterdrückt und der Fehlercode innerhalb der Anwendung mit der Funktion socket_last_error() aufgefangen. Sie können auch die Funktion socket_strerror() mit diesem Fehlercode aufrufen, um einen String, der den Fehler beschreibt, zu erhalten. Nähere Informationen finden Sie bei diesen beiden Funktionen.

> Anmerkung: Die `E_WARNING`-Meldungen, die von der Socket-Extension generiert werden, sind auf Englisch, aber die Meldungen, die Sie extra abfragen können, erscheinen in der entsprechenden Sprache, die Sie eingestellt haben (`LC_MESSAGES`):

>     Warning - socket_bind() unable to bind address [98]: Die Adresse wird bereits verwendet

# Beispiele

Beispiel 1. Socket Beispiel: Einfacher TCP/IP Server

Dieses Beispiel zeigt einen einfachen Echo-Server. Passen Sie die Variablen `address` und `port` an Ihre Systemumgebung an und führen Sie das Skript aus. Dann können Sie sich mit einem Befehl wie: telnet 192.168.1.53 10000 (bei dem adress und port an Ihre Umgebung angepasst ist) mit dem Server verbinden. Alles, was Sie eingeben, wird an den Server geschickt und von diesem wieder an Sie zurückgegeben. Um die Verbindung zu trennen, geben sie 'quit' ein.

    #!/usr/local/bin/php -q
    <?php
    error_reporting (E_ALL);

    /* Das Skript wartet auf hereinkommende Verbindungsanforderungen. */
    set_time_limit (0);

    /* Die implizite Ausgabe wird eingeschaltet, so dass man sieht, was gesendet wurde. */
    ob_implicit_flush ();

    $address = '192.168.1.53';
    $port = 10000;

    if (($sock = socket_create (AF_INET, SOCK_STREAM, 0)) < 0) {
        echo "socket_create() fehlgeschlagen: Grund: " . socket_strerror ($sock) . "\n";
    }

    if (($ret = socket_bind ($sock, $address, $port)) < 0) {
        echo "socket_bind() fehlgeschlagen: Grund: " . socket_strerror ($ret) . "\n";
    }

    if (($ret = socket_listen ($sock, 5)) < 0) {
        echo "socket_listen() fehlgeschlagen: Grund: " . socket_strerror ($ret) . "\n";
    }

    do {
        if (($msgsock = socket_accept($sock)) < 0) {
            echo "socket_accept() fehlgeschlagen: Grund: " . socket_strerror ($msgsock) . "\n";
            break;
        }
        /* Anweisungen senden. */
        $msg = "\nWillkommen auf dem PHP Testserver.  \n" .
            "Um zu beenden, geben Sie 'quit' ein. Um den Server herunterzufahren, geben Sie 'shutdown' ein.\n";
        socket_write($msgsock, $msg, strlen($msg));

        do {
            if (FALSE === ($buf = socket_read ($msgsock, 2048))) {
                echo "socket_read() fehlgeschlagen: Grund: " . socket_strerror ($ret) . "\n";
                break 2;
            }
            if (!$buf = trim ($buf)) {
                continue;
            }
            if ($buf == 'quit') {
                break;
            }
            if ($buf == 'shutdown') {
                socket_close ($msgsock);
                break 2;
            }
            $talkback = "PHP: Sie haben '$buf' eingegeben.\n";
            socket_write ($msgsock, $talkback, strlen ($talkback));
            echo "$buf\n";
        } while (true);
        socket_close ($msgsock);
    } while (true);

    socket_close ($sock);
    ?>

Beispiel 2. Socket Beispiel: Einfacher TCP/IP Client

Dieses Beispiel zeigt einen einfachen HTTP-Client, der einen einzelnen Request absetzen kann. Er verbindet sich mit einer Seite, setzt einen HEAD-Request ab, gibt die Antwort zurück und wird beendet.

    <?php
    error_reporting (E_ALL);

    echo "<h2>TCP/IP Verbindung</h2>\n";

    /* Den Port des WWW-Dienstes holen. */
    $service_port = getservbyname ('www', 'tcp');

    /* Die IP-Adresse des Zielhosts holen. */
    $address = gethostbyname ('www.example.com');

    /* einen TCP/IP Socket erzeugen. */
    $socket = socket_create (AF_INET, SOCK_STREAM, 0);
    if ($socket < 0) {
        echo "socket_create() fehlgeschlagen: Grund: " . socket_strerror ($socket) . "\n";
    } else {
        echo "OK.\n";
    }

    echo "Versuche, eine Verbindung zu '$address' auf Port  '$service_port' aufzubauen ...";
    $result = socket_connect ($socket, $address, $service_port);
    if ($result < 0) {
        echo "socket_connect() fehlgeschlagen.\nGrund: ($result) " . socket_strerror($result) . "\n";
    } else {
        echo "OK.\n";
    }

    $in = "HEAD / HTTP/1.0\r\n\r\n";
    $out = '';

    echo "Einen HTTP HEAD Request senden ...";
    socket_write ($socket, $in, strlen ($in));
    echo "OK.\n";

    echo "Die Antwort lesen:\n\n";
    while ($out = socket_read ($socket, 2048)) {
        echo $out;
    }

    echo "Den Socket schliessen ...";
    socket_close ($socket);
    echo "OK.\n\n";
    ?>

Zurück | Zum Anfang | Nach vorne
snmpwalkoid | Nach oben | socket_accept