Home
Navigation
Impressum
Coder Welten - Programmierung und Optimierung
Coder Welten
 
 

 

 

OOP: Klasse zum Aufbau einer TCP/IP Socket Verbindung

Abruf wie durch einen einfachen Bot - I

Übersicht » Einführung OOP

Beispiele:

  1. Parserklasse (eine simple Parserklasse für ein einfaches XML-Dokument)
  2. Socket Klasse (eine TCP/IP Socket Klasse zum Abruf wie durch einen Bot)
  3. Formular Klasse (Socket-Klasse mit einer Formular-Klasse kombinieren)
  4. cURL Klasse (eine cURL Session initialisieren und ausführen)
  5. CSV Klasse (zum Auslesen (rückwärts) von umfangreichen CSV-Dateien)

Voraussetzungen und Aufruf des Scripts

Das Script auf dieser Seite setzt eine Socket-Erweiterung von PHP voraus, um eine hardwarenahe Schnittstelle zum Aufbau einer Socket-Verbindung zwischen Client und Server zu nutzen, wobei diese Erweiterung auf BSD Sockets aufbaut. Das Kürzel BSD steht in diesem Zusammenhang für Berkeley Software Distribution. Um das Script nutzen zu können, muss der Socket-Support ermöglicht sein. Kontrollieren Sie vor einem ersten Test, ob in der PHP Info ein Eintrag wie "Sockets Support enabled" existiert. Falls nicht, suchen Sie in der php.ini (falls Zugriff auf die php.ini besteht) nach dem Eintrag extension=php_sockets.dll und kommentieren diesen durch die Entfernung des vorangestellten Semikolons ein. Weitere Hinweise siehe [1].
Für den Fall, dass sich ein "Sockets Support" nicht ermöglichen lassen sollte, sei auf das Beispiel "cURL Klasse" verwiesen, welches ebenfalls eine Ausgabe wie dieses Listing liefert. Einziger Unterschied, Port und IP-Adresse werden nicht mit eingeblendet.

Nach dem ersten Aufruf des Scripts im Browser sowie der Eingabe und Übermittlung einer URL mit Hilfe des Formulars, enthält die Ausgabe die vom Server erhaltene Response mit dem HTTP-Header (Message Header) und dem Message Body. Somit das, was auch ein einfacher Bot sehen würde, wenn er eine Webseite besucht.


Vorbemerkung und Einzelheiten

Vorbemerkung: Bei der Beschreibung wird der Begriff Funktionen statt Methoden (wie bei OOP üblich) verwendet, da es sich um Funktionen handelt, die von PHP und anderen Sprachen zur Verfügung gestellt und in diesen Sprachen als Funktionen beschrieben werden.

Weiterhin wurde nur eine Klasse für die eigentliche TPC/IP Socket Verbindung definiert, die Auswertung der vom Formular übermittelten Daten erfolgt hingegen im prozeduralen Stil. Auf eine durchgängig objektorientierte Programmierung wurde zu Gunsten der Einfachheit in diesem Beispiel verzichtet. Dass es auch anders geht, beweisen die Beispiele unter den Menüpunkten "Formular Klasse" und "cURL Klasse".

Einzelheiten: Im ersten Teil der Klasse werden die erforderlichen Angaben für den Request gesetzt. Daran anschließend wird mit der Funktion getservbyname der passende Port für den angegebenen Dienst (www) und für das angegebene Protokoll (TPC) gesucht, sowie mit der Funktion gethostbyname die entsprechende IPv4-Adresse ausgelöst. Mit socket_create wird der Endpunkt (Socket) für die Kommunikation erzeugt, wobei folgende Parameter gesetzt werden:

AF_INET für auf IPv4 beruhende Internet-Protokolle
SOCK_STREAM Socket-Typ für das TCP-Protokoll
SOL_TCP Konstante für das TCP-Protokoll

Im weiteren Verlauf wird mit socket_connect eine Verbindung zur angegebenen Adresse und zum ermittelten Port aufgebaut und mit socket_write die Request-Daten geschrieben. Die if-Statements mit socket_strerror dienen lediglich der Anzeige des Verlaufs bzw. der Ermittlung von Socket-Fehlern. In einer Schleife (while) werden die übermittelten Daten mit der Funktion socket_read gelesen, wobei die Anzahl der höchstens zu lesenden Bytes zwar anzugeben ist, nur bei den Tests kleine Werte von PHP scheinbar nicht beachtet wurden, eine fehlen Angabe hingegen schon. Mit socket_close wird zum Abschluss der Klasse die Socket-Verbindung geschlossen.

Für die Ausgabe ist es neben der Erstellung eines Objektes erforderlich, die übermittelten Werte den öffentlichen Variablen der Klasse zuzuweisen. Beides, weiterhin die eigentliche Ausgabe, erfolgt mit den letzten Code-Zeilen.

Code-Listing/Script zum Aufbau einer TCP/IP Socket Verbindung:

<?php
error_reporting(E_ALL);

$domain = "www.example.com";
$seite  = "/";
$seitef = "";

/*-- Überprüfung der vom Formular übermittelten URL ---------------------------*/

if (isset($_GET["abrufen"]) and !empty($_GET["abrufen"])) {

    $abrufen = trim($_GET["abrufen"]);
    $hrefpos = stripos($abrufen, "http://");
    $abrufen = preg_replace("/[^a-zA-Z0-9.:?&\/=_-]/", "", $abrufen);

    if ($hrefpos === false) {
        $abrufen = "http://".$abrufen;
    }
    $geparst = parse_url($abrufen);

    if (isset($geparst["host"]) and !empty($geparst["host"])) {
        $domain = $geparst["host"];
    }
    if (isset($geparst["path"]) and !empty($geparst["path"])) {
        $seite  = $geparst["path"];
        $seitef = $seite;

        if (isset($geparst["query"]) and !empty($geparst["query"])) {
            $seite .= "?".$geparst["query"];
        }
    }
}
?>
<!DOCTYPE html>
<html>

<head>
<title>Abruf wie durch Bot</title>
</head>

<body>
<div style="text-align:center">
<h1>Abruf wie durch Bot</h1>

<?php echo htmlentities($domain.$seitef, ENT_QUOTES)."<br>\n"; ?>

<form action="<?php echo basename($_SERVER["PHP_SELF"]); ?>" method="get">
  <input type="text" name="abrufen" size="60" maxlength="80"><br>
  <input type="reset" value=" Reset ">
  <input type="submit" value=" Senden ">
</form>
</div>
<?php

/*-- Klasse zum Aufbau einer TCP/IP Socket Verbindung -------------------------*/

class WieBot {

    public $domain = "";
    public $seite  = "";

    public function getVerbindung() {

        $request  = "GET ".$this->seite." HTTP/1.1\r\n";
        $request .= "Host: ".$this->domain."\r\n";
        $request .= "User-Agent: Mozilla/5.0 (compatible; Demo Botklasse 0.1)\r\n";
        $request .= "Connection: Close\r\n\r\n";
        $dienstp  = getservbyname("www", "tcp");
        $adresse  = gethostbyname($this->domain);
        $socket   = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
        $gebeaus  = "";

        if ($socket != false) {
            $sockett = "TCP/IP Socket (Endpunkt) wurde erzeugt: OK.<br>\n";
        }
        else {
            $sockett = "TCP/IP Socket (Endpunkt) wurde nicht erzeugt: Grund: ".
            socket_strerror($socket)."<br>\n";
        }

        $verbindg = socket_connect($socket, $adresse, $dienstp);

        if ($verbindg != false) {
            $verbindgt = "Eine Verbindung zu ".$adresse." ".
            "über Port ".$dienstp." wurde aufgebaut: OK.<br>\n";
        }
        else {
            $verbindgt = "Der Verbindungsaufbau schlug fehl. ".
            "Grund: ".$verbindg." ".socket_strerror($verbindg)."<br>\n";
        }

        $gesendet = socket_write($socket, $request, strlen($request));

        if ($gesendet !== false) {
            $gesendett = "Ein HTTP GET Request wurde gesendet: OK.<br>\n";
        }
        else {
            $gesendett = "Es wurde kein Request gesendet!<br>\n";
        }

        while ($ausgabe = socket_read($socket, 1000)) {

            $gebeaus .= htmlentities($ausgabe, ENT_QUOTES);
        }

        socket_close($socket);
        $endeges = "Der Socket (Endpunkt) wurde geschlossen: OK.<br>\n\n";

        return "<span style=\"color:#862000\">".$sockett.$verbindgt.$gesendett."</span>\n<hr>\n".
        "<pre>".$gebeaus."</pre>\n<hr>\n<span style=\"color:#862000\">".$endeges."</span>\n";
    }
}
/*-------------------------------------------------------------------------------
 Erzeugen und Instanziieren des Objektes WieBot, Zuweisung der Variablen-Werte
 von $domain und $seite, Ausgabe des Rückgabewertes der Funktion getVerbindung.
 --------------------------------------------------------------------------------
*/
$wiebot = new WieBot();
$wiebot->domain = $domain;
$wiebot->seite  = $seite;

echo $wiebot->getVerbindung();
?>
</body>
</html>

Hinweis zu 1: Bei einem Test wurde der Fehler-Code 406 ausgegeben. Als Grund stellte sich heraus, dass der Server, auf dem das Script abgelegt wurde, kein http:// im QueryString erlaubte. Bei Eingabe der URL ohne http:// ins Formular erfolgte der Abruf wie erwartet ohne Probleme.

Simple Parserklasse « / » Formular Klasse

 

Copyright © Verlag Horst Müller - Stendal - 2006 - Impressum - Datenschutz - Nutzungsbedingungen