quakenet:#php Tutorial

Author: Progman, zuletzt bearbeitet von progman @ 2003/07/26 19:10:38

Bitte beachten Sie, dass die Tutorialkapitel zusammenhängen. Wenn sie direkt auf ein Kapitel verlinkt wurden müssen Sie gegebenenfalls die vorherigen Kapitel auch lesen. Achten Sie beim lesen darauf, dass Sie kein Kapitel überspringen.

Zugriff auf externe Rechner

  1. Verbindung zu einem externen Rechner aufbauen
  2. Mit dem Server kommunizieren
  3. Protokolle im Internet
  4. Ein HEAD Request an einem HTTP-Server schicken

1. Verbindung zu einem externen Rechner aufbauen

Es kann Situationen geben, da möchte man auf einen externen Rechner zugreifen und dort dann etwas auslesen. Mit PHP kann man z.B. in ein IRC-Netz connecten, um dort die Channelstats des eigenen Clans auszulesen. Oder man kann aber auch mit PHP auf einen Gameserver connecten und auslesen, wieviele Spieler grad auf dem Server sind. Wir können auch andere HTML-Seiten auf fremden Server öffnen. Doch wenn allow_url_fopen auf on steht, kann man auch fopen benutzen.

Um sich mit einem anderen Rechner zu verbinden benutzt man die Funktion fsockopen. Diese hat 5 Parameter wobei die letzen 3 optional sind. Doch wir werden alle Parameter benutzen. Hier ein Beispiel wie man eine Verbindung zu einem Webserver aufbaut.

<?php
    fsockopen
('example.com', 80, $errno, $error, 5);
?>

Dies baut eine Verbindung zum Server example.com über den Port 80 (http) auf. Falls ein Fehler auftrat werden die Fehlerinformationen in den Variablen $errno und $error gespeichert. Die 5 gibt das Timeout in Sekunden an, wie lange PHP warten soll, bis eine Verbindung aufgebaut werden kann. Nach dieser Zeit bricht PHP ab und es wird eine Timeout-Fehlermeldung in den Error-Variablen gespeichert. Standardmäßig wird eine TCP Verbindung benutzt. Wenn man eine UDP Verbindung aufbauen möchte (braucht man bei GameServer) muss man die Angabe udp:// im Hostname angeben

<?php
    fsockopen
('udp://192.168.0.1', 27015, $errno, $error, 10);
?>

Die Funktion liefert einen Handler zurück, den man für weitere Funktionen benötigt. Dieser Handler ist false, wenn keine Verbindung aufgebaut werden konnte. Wir können deshalb recht einfach eine If-Abfrage bauen.

<?php
    $fp
= fsockopen('example.com', 80, $errno, $error, 5);
    if(!
$fp) {
        echo
"Konnte keine Verbindung zum Rechner aufbauen";
        echo
$error."(".$errno.")";
        die();
    }
?>

Oder einfacher

<?php
    $fp
= fsockopen('example.com', 80, $errno, $error, 5) OR die($error."(".$errno.")");
?>

Eine Verbindung zu einem anderen Rechner muss richtig beendet werden. Dies machen wir mit der Funktion fclose.

<?php
    $fp
= fsockopen('example.com', 80, $errno, $error, 5) OR die($error."(".$errno.")");

    
// Befehle senden bzw. empfangen

    
fclose($fp);
?>

2. Mit dem Server kommunizieren

Nachdem wir eine Verbindung aufgebaut haben, können wir uns mit dem Server unterhalten. Wir senden z.B. ein Befehl zum Server und lesen das Ergebnis aus. Dafür gibt es 2 Funktionen.

  1. fwrite - Der erste Parameter ist der Handler der Verbindung. Der zweite Parameter ist der String den man zum Server schicken möchte.

  2. fread - Der erste Parameter ist wieder der Handler der Verbindung. Der zweite Parameter gibt an wieviele Zeichen gelesen werden sollen. Den sollte man auf 1k, also 1024 setzen. Bei neueren PHP Versionen kann man diesen Parameter weglassen, dann wird automatisch eine Länge von 1024 genommen.

Nützlich ist auch die Funktion feof. Mit dieser Funktion können wir prüfen, ob etwas aus der Verbindung zu lesen ist oder nicht (EOF - End Of File). Man benutzt sie in einer While-Schleife.

Ein Beispiel Script könnte so aussehen.

<?php
    $fp
= fsockopen('example.com', 80, $errno, $error, 5) OR die($error."(".$errno.")");
    
fwrite($fp, "irgendein Text zum Server schicken");
    while(!
feof($fp)) {
        
// es ist was zum lesen da.
        
$buffer = fread($fp, 1024);
        echo
$buffer;
    }
    
fclose($fp); // Verbindung beenden
?>

Hier wird zuerst eine Verbindung zum Server aufgebaut. Dann wird etwas zum Server geschickt. Mit der While-Schleife prüfen wir dann ob etwas zu empfangen ist. Wenn ja, also wenn feof false liefert, wird mit fread 1024 Zeichen, ein String bis zu einem Zeilenumbruch (\n) oder ein String bis zum Ende des Inhalts (in der Fachsprache als EOF bezeichnet) ausgelesen, je nach dem, was früher eintritt. Nach der While-Schleife wird dann die Verbindung beendet.

3. Protokolle im Internet

Nach dem man eine Verbindung zum Server aufgebaut hat, kann man nun mit ihm 'sprechen'. Doch was für eine 'Sprache' spricht denn der Server? Im Internet nennt man diese Sprachen, mit denen sich Client und Server unterhalten Protokolle. Mit einem Protokoll wird genau festgelegt, wie eine Informationsaustausch von Client und Server von statten geht. Viele Protokolle sind als RFC vorhanden. Das HTTP Protokoll gibt es in verschiedenen Versionen. HTTP 1.0 wird als RFC1945 definiert und HTTP 1.1 als RFC2068. Eine entsprechende Suche in Google sollte die RFCs finden.

4. Ein HEAD Request an einem HTTP-Server schicken

Als Beispiel senden wir mal einen HEAD Request an einem Webserver. In den RFCs steht, dass man damit Informationen über eine Resource bekommen kann, üblicherweise eine Datei.

Zurerst bauen wir eine Verbindung zum Server auf.

<?php
    $fp
= fsockopen('localhost', // 127.0.0.1
                    
80,          // Port 80 (HTTP)
                    
$errno,      // Fehlernummer
                    
$error,      // Fehlermeldung
                    
5)           // Timeout in Sekunden
          
OR                     // wenn der Aufbau nicht erfolgreich war
          
die(                   // dann 'stirb'
              
$error.            // Fehlermeldung
              
"(".               //
              
$errno.            // mit Fehlernummer
              
")"                //
          
);

    
// Mach was mit der Verbindung

    
fclose($fp); // Verbindung beenden
?>

Ihr könnt natürlich die Kommentare einfach weglassen. Irgendwann hat man die Funktion drauf. Nun senden wir ein HEAD-Request.

<?php
    $fp
= fsockopen('localhost', // 127.0.0.1
                    
80,          // Port 80 (HTTP)
                    
$errno,      // Fehlernummer
                    
$error,      // Fehlermeldung
                    
5)           // Timeout in Sekunden
          
OR                     // wenn der Aufbau nicht erfolgreich war
          
die(                   // dann 'stirb'
              
$error.            // Fehlermeldung
              
"(".               //
              
$errno.            // mit Fehlernummer
              
")"                //
          
);
    
fwrite($fp, "HEAD / HTTP/1.0\r\n");

    
fclose($fp); // Verbindung beenden
?>

Wichtig ist, was man häufig vergisst, dass man eine Request-Zeile mit einem \r\n abschließt. Aus gewohnheit schreibt man nur ein einfaches \n. Deshalb muss man hier aufpassen. Eine kompletter Request wird mit einer leeren Request-Zeile abgeschlossen.

<?php
    $fp
= fsockopen('localhost', // 127.0.0.1
                    
80,          // Port 80 (HTTP)
                    
$errno,      // Fehlernummer
                    
$error,      // Fehlermeldung
                    
5)           // Timeout in Sekunden
          
OR                     // wenn der Aufbau nicht erfolgreich war
          
die(                   // dann 'stirb'
              
$error.            // Fehlermeldung
              
"(".               //
              
$errno.            // mit Fehlernummer
              
")"                //
          
);
    
fwrite($fp, "HEAD / HTTP/1.0\r\n");
    
fwrite($fp, "\r\n"); // Request beenden

    
fclose($fp); // Verbindung beenden
?>

Nun können wir das Ergebnis abfragen. Dies machen wir mit der While-Schleife von oben.

<?php
    $fp
= fsockopen('localhost', // 127.0.0.1
                    
80,          // Port 80 (HTTP)
                    
$errno,      // Fehlernummer
                    
$error,      // Fehlermeldung
                    
5)           // Timeout in Sekunden
          
OR                     // wenn der Aufbau nicht erfolgreich war
          
die(                   // dann 'stirb'
              
$error.            // Fehlermeldung
              
"(".               //
              
$errno.            // mit Fehlernummer
              
")"                //
          
);
    
fwrite($fp, "HEAD / HTTP/1.0\r\n");
    
fwrite($fp, "\r\n"); // Request beenden
    
while(!feof($fp)) {
        
$buffer = fread($fp, 1024);
        
// ..
    
}
    
fclose($fp); // Verbindung beenden
?>

Es wird nun Zeile für Zeile durchgegangen und in $buffer gespeichert. Diese Zeile enthält auch die Zeichenkette \r\n. Da man diese nicht im Browser sieht, ersetzen wir diese durch eine Sichbare Zeichenkette.

<?php
    $fp
= fsockopen('localhost', // 127.0.0.1
                    
80,          // Port 80 (HTTP)
                    
$errno,      // Fehlernummer
                    
$error,      // Fehlermeldung
                    
5)           // Timeout in Sekunden
          
OR                     // wenn der Aufbau nicht erfolgreich war
          
die(                   // dann 'stirb'
              
$error.            // Fehlermeldung
              
"(".               //
              
$errno.            // mit Fehlernummer
              
")"                //
          
);
    
fwrite($fp, "HEAD / HTTP/1.0\r\n");
    
fwrite($fp, "\r\n"); // Request beenden
    
while(!feof($fp)) {
        
$buffer = fread($fp, 1024);
        
$buffer = str_replace("\r\n", '\r\n'."\n", $buffer);
    }
    
fclose($fp); // Verbindung beenden
?>

Bevor ich die Zeile ausgebe, setze ich noch den Content-Type auf text/plain. Dies machen wir vor der Schleife.

<?php
    $fp
= fsockopen('localhost', // 127.0.0.1
                    
80,          // Port 80 (HTTP)
                    
$errno,      // Fehlernummer
                    
$error,      // Fehlermeldung
                    
5)           // Timeout in Sekunden
          
OR                     // wenn der Aufbau nicht erfolgreich war
          
die(                   // dann 'stirb'
              
$error.            // Fehlermeldung
              
"(".               //
              
$errno.            // mit Fehlernummer
              
")"                //
          
);
    
fwrite($fp, "HEAD / HTTP/1.0\r\n");
    
fwrite($fp, "\r\n"); // Request beenden
    
header('Content-Type: text/plain'); // Content-Type verändern
    
while(!feof($fp)) {
        
$buffer = fread($fp, 1024);
        
$buffer = str_replace("\r\n", '\r\n'."\n", $buffer);
    }
    
fclose($fp); // Verbindung beenden
?>

Nun geben wir einfach nur die Variable $buffer in der Schleife aus.

<?php
    $fp
= fsockopen('localhost', // 127.0.0.1
                    
80,          // Port 80 (HTTP)
                    
$errno,      // Fehlernummer
                    
$error,      // Fehlermeldung
                    
5)           // Timeout in Sekunden
          
OR                     // wenn der Aufbau nicht erfolgreich war
          
die(                   // dann 'stirb'
              
$error.            // Fehlermeldung
              
"(".               //
              
$errno.            // mit Fehlernummer
              
")"                //
          
);
    
fwrite($fp, "HEAD / HTTP/1.0\r\n");
    
fwrite($fp, "\r\n"); // Request beenden
    
header('Content-Type: text/plain'); // Content-Type verändern
    
while(!feof($fp)) {
        
$buffer = fread($fp, 1025);
        
$buffer = str_replace("\r\n", '\r\n'."\n", $buffer);
        echo
$buffer;
    }
    
fclose($fp); // Verbindung beenden
?>

Das wars. Nun testen wir das Script. Wir senden folgenden Request.

HEAD / HTTP/1.0\r\n
\r\n
        

Die Ausgabe könnte wie folgt aussehen.

HTTP/1.1 200 OK\r\n
Date: Wed, 30 Apr 2003 13:42:59 GMT\r\n
Server: Apache/1.3.26 (Unix) Debian GNU/Linux PHP/4.1.2\r\n
Last-Modified: Sat, 26 Oct 2002 09:12:14 GMT\r\n
ETag: "3b783-100e-3dba5c6e"\r\n
Accept-Ranges: bytes\r\n
Content-Length: 4110\r\n
Connection: close\r\n
Content-Type: text/html; charset=iso-8859-1\r\n
\r\n
        

Hier findet man ein paar nützliche Informationen. Z.B. die erste Zeile. Hier sieht man, dass der Server mit einer "200 OK"-Message Antwortet. Dies sagt in diesem Fall dass alles in Ordnung ist. Es gibt z.B. 400 für Bad Request oder aber auch das bekannte 404 für File not Found. Das wird aber auch alles genauer in den RFCs erklärt.

Fragen zum aktuellen Thema

  1. Was sind RFCs?
  2. Warum muss man bei den Zeilenumbruch genau aufpassen
Was sind RFCs?

RFC steht für Request for Comments. Sie definieren einen Standard für ein Protokoll, wie z.B. das HTTP-Protokoll (eigentlich sagt man "für das HTTP" weil in der Abkürzung HTTP schon das Wort "Protocol" drinsteht) oder das IRC-Protokoll. Eine Liste von RFCs mit integrierter Suchmaschine findet man auf http://www.rfc-editor.org/ .

Warum muss man bei den Zeilenumbruch genau aufpassen

'Zeilen' in einem Protokoll werden üblicherweise mit der Zeichenkette \r\n abgeschlossen. Da man dies oft mit dem PHP-Zeilenumbruch \n verwechselt muss man hier genau aufpassen. Ein \r\n nennt man auch CRLF (carriage return line feed).

Nach oben