Thomas Steinheber: Push des Servers, sobald änderung in seiner DB

Hallo,
bin ba-student in stuttgart, und arbeite derzeit an einer supply-chain-management-demonstration.
Ein problem, das ich im moment habe:

Ich will, dass sobald ein client eine bestimmte db-änderung auf dem server bewirkt, bei einem anderen client ein fenster aufpoppt, das ich dann mit entsprechenden inhalten versehen kann.

Bis jetzt basiert das ganze auf php. Aber dieses problem wird wohl durch php nicht zu lösen sein, es sei denn, ich frage alle 1/10 sekunde meine datenbank vom client aus ab, was mir aber eine ziemliche last erzeugt.

Danke schonmal für eure Hilfe!!

  1. Hallo,

    nimdd och zum Beispiel ein Java-Applet welches per Stream den Serverstatus abfragt.

    Gruß Jan

    1. nimdd och zum Beispiel ein Java-Applet welches per Stream den Serverstatus abfragt.

      Vielleicht hätte ich besser sagen sollen, dass die mittel, die mir zu beginn des projekts gestellt waren, sich auf php und db2 beschränkten.
      Klar ist mir, wie gesagt, dass dies mit php so gut wie unmöglich ist.

      In java bin ich leider noch nicht so der crack.
      Du meintest aber schon, dass das java-applet auf dem server laufen soll, oder?
      Bei der "überwachung" der db soll eigentlich nur auf genau einen datensatz und hier auf den inhalt einer spalte geachtet werden.

      Dann kann ich auch mit dem applet genau diese daten überprüfen und wenn sich was ändert die änderung feststellen und bei einem client eine aktion ausführen lassen, wie eben das aufpoppen eines fensters?

      Danke schonmal,

      Das ist ein Problem, das ich heute oder morgen gelöst haben muss.
      Ich sitze sozusagen auf Kohlen...

      Gruss Thomas

      1. Hallo,

        bin selber BA-Student und unter Zeitdruck in eine Programmiersprache einarbeiten ist doch toll - aber bis morgen früh... na ja. :o)

        Also: Ich würde es so machen:

        Auf dem Server läuft ein kleines (Java)-Progrämmchen welches bei Änderungen in der DB eine Nachricht an alle Clients sendet.

        Die Clients selber sind Java-Applets die im Browser der Users aufgerufen werden und auf die Statusänderung reagieren.

        Gruß Jan

        1. bin selber BA-Student und unter Zeitdruck in eine Programmiersprache einarbeiten ist doch toll - aber bis morgen früh... na ja. :o)

          Hallo herr kollege.
          Aber nicht aus Stuttgart, oder?

          Also: Ich würde es so machen:

          Auf dem Server läuft ein kleines (Java)-Progrämmchen welches bei Änderungen in der DB eine Nachricht an alle Clients sendet.

          Die Clients selber sind Java-Applets die im Browser der Users aufgerufen werden und auf die Statusänderung reagieren.

          Tja, ob es für mich nur ein progrämmchen ist, das muss ich mir noch überlegen ;)
          Aber ich hoffe doch, du willst mir nicht ernsthaft sagen, dass ich meinen ganzen php-code über´n haufen werfen soll.
          Das java-applet, das auf den clients läuft soll ja nur für das aufpoppen eines kleinen infofensters zuständig sein, in dem die veränderungen der datenbank stehen...

          Ich hab seit gestern schon befürchtet, dass es auf java rauslaufen wird...
          Dann lernen wir halt mal java

          1. Nein, ich bin aus Dresden und ja, das Programm ist dann nur für das Popup zuständig. Viel Spass. :o)

            Gruß Jan

          2. Hi,

            Tja, ob es für mich nur ein progrämmchen ist, das muss ich mir noch überlegen ;)
            Aber ich hoffe doch, du willst mir nicht ernsthaft sagen, dass ich meinen ganzen php-code über´n haufen werfen soll.
            Das java-applet, das auf den clients läuft soll ja nur für das aufpoppen eines kleinen infofensters zuständig sein, in dem die veränderungen der datenbank stehen...

            Nein. Es ist vor allem dafür da, die socket-Verbindung zum Server offenzuhalten.
            Das Popup kannst Du sowohl vom Applet aus als Java-Fenster als auch durch Javascript erzeugen (Javascript kann auf ein Applet zugreifen und ein Applet kann auf Javascript zugreifen...)

            cu,
            Andreas

            --
            Der Optimist: Das Glas  ist halbvoll.  - Der Pessimist: Das Glas ist halbleer. - Der Ingenieur: Das Glas ist doppelt so groß wie nötig.
            http://mud-guard.de/? http://www.andreas-waechter.de/
  2. Hi,

    bin ba-student in stuttgart, und arbeite derzeit an einer supply-chain-management-demonstration.

    ba?

    Ich will, dass sobald ein client eine bestimmte db-änderung auf dem server bewirkt, bei einem anderen client ein fenster aufpoppt, das ich dann mit entsprechenden inhalten versehen kann.
    Bis jetzt basiert das ganze auf php.

    Also vermutlich auf http. Auf einem "verbindungslosem" Protokoll also.
    Ein Protokoll, bei dem der Server nicht in der Lage ist, Verbindung mit den Clients aufzunehmen, sondern darauf warten muß, daß der Client einen Request schickt.
    Ein für derartige Zwecke ziemlich ungeeignetes

    Aber dieses problem wird wohl durch php nicht zu lösen sein, es sei denn, ich frage alle 1/10 sekunde meine datenbank vom client aus ab, was mir aber eine ziemliche last erzeugt.

    10 http-Requests in der Sekunde?
    Selbst wenn Du nur 1 mal in der Sekunde einen request absenden würdest:
    Ist diese hohe Rate der Aktualisierung überhaupt notwendig?
    Auf das Popup muß doch sowieso ein Mensch dann in irgendeiner Weise reagieren (sonst hat das Popup keinen Sinn).
    Und unter diesen Umständen sind 3 bis 4 Refreshs in der Minute m.E. ausreichend.

    Sinnvoller wäre m.E. aber die Verwendung von (z.B.) Java-Clients, die über socket-Verbindungen mit dem Server kommunizieren (und wobei der Server auch von sich aus an einen Client senden kann).

    cu,
    Andreas

    --
    Der Optimist: Das Glas  ist halbvoll.  - Der Pessimist: Das Glas ist halbleer. - Der Ingenieur: Das Glas ist doppelt so groß wie nötig.
    http://mud-guard.de/? http://www.andreas-waechter.de/
  3. Hab grad in phpinfo etwas von sockets usw gefunden...:

    #!/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);
    ?>

    Hört sich sowas gut an??
    Soweit ich´s verstanden habe, wartet hier der Server, bis er etwas geschickt bekommt.
    Und wenn der client was in der datenbank ändern will, dann schickt er ja die daten an den server.
    Der kann doch diese daten, die er bekommen hat an einen anderen client responden, oder??

    1. Hi,

      Soweit ich´s verstanden habe, wartet hier der Server, bis er etwas geschickt bekommt.
      Und wenn der client was in der datenbank ändern will, dann schickt er ja die daten an den server.
      Der kann doch diese daten, die er bekommen hat an einen anderen client responden, oder??

      Du brauchst dann aber trotzdem einen Client, der ebenfalls einen socket aufmachen kann.
      Womit wir wieder beim Java-Applet wären...

      cu,
      Andreas

      --
      Der Optimist: Das Glas  ist halbvoll.  - Der Pessimist: Das Glas ist halbleer. - Der Ingenieur: Das Glas ist doppelt so groß wie nötig.
      http://mud-guard.de/? http://www.andreas-waechter.de/
      1. Du brauchst dann aber trotzdem einen Client, der ebenfalls einen socket aufmachen kann.
        Womit wir wieder beim Java-Applet wären...

        zum client, der den socket aufmachen soll habe ich folgendes gefunden:

        <?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";
        ?>

        Ja, aber deswegen poppt ja noch lange kein fenster....
        Ich mein auch, dass ich an einem java-applet nicht vorbeikommen werde...

        1. Hi,

          Du brauchst dann aber trotzdem einen Client, der ebenfalls einen socket aufmachen kann.
          Womit wir wieder beim Java-Applet wären...
          zum client, der den socket aufmachen soll habe ich folgendes gefunden:
          <?php

          PHP läuft auf dem Server, nicht auf dem Client.
          Mit dem PHP-Zeug kann Dein Server Verbindungen zu anderen Rechnern aufnehmen, aber nicht der Browser...

          cu,
          Andreas

          --
          Der Optimist: Das Glas  ist halbvoll.  - Der Pessimist: Das Glas ist halbleer. - Der Ingenieur: Das Glas ist doppelt so groß wie nötig.
          http://mud-guard.de/? http://www.andreas-waechter.de/
  4. Hallo Thomas,

    habe den Thread gelesen.... hmmmm ..... !
    Die Arbeit ist sehr aufwendig hier noch ein Java Applet einzubauen .... vielmehr zusätzlich eine PHP Socket to Java Applet Kommunikation. Wesentlich schneller kommst du mit der Pushlet Technologie weiter !

    Du willst versuchen eine HTML Seite oder Projekt mit Live Daten zu versorgen !

    Das ursächliche Problem ist das ein HTTP Client(Browser) nicht die Möglichkeit bietet auf Verbindungen zu lauschen um auf requests zu antworten!

    Die ständige Nachfrage des Clients nach neuen Daten ist hier, so wie es zunächst aussieht, eine mögliche Lösung des Problems ("polling").

    Der Nachteil ist die Lasst des Servers ! Hier kommen innerhalb bestimmter Zeitabstände requests(Anfragen) herein. Wenn man sich dafür entscheidet damit zu arbeiten solltest du eine "Cache" Funktion in dein PHP Script einbauen um zu verhindern das bei jedem Aufruf des main Scriptes die Datenbank belastet wird, auch wenn keine neuen Daten vorliegen.

    Einen neuen Output nur senden wenn auch wirklich neue Daten vorliegen!
    Das lässt sich sehr gut mit den HTTP Headern erledigen die dem Client anhand des (last mod) Headers sagen das die Seite sich nicht verändert  hat. So wird kein zusätzlicher Traffic erzeugt und der Client verarbeitet die HTML Seite aus dem lokalen Browser-Cache.

    Eine weitere Möglichkeit ist das "pushen" (Java Pushlet)!
    Über JavaScript bietet sich die Möglichkeit einen Kommunikationskanal offen zu halten. (Socket)

    Der Browser öffnet einen Socket zum Server - und sendet eine Anfrage(request) - der Server antwortet(response) - und der Socket wird geschlossen! Hier liegt die Möglichkeit..... zwar wird hier das HTTP Protokoll ein bischen vergewaltigt..... aber es funktioniert.

    Dieser Socket muss geöffnet bleiben ! .... also kein close() [wenn es das in PHP gibt ???]

    Dadurch kannst du nach und nach Daten in den Stream schreiben. Das wird z.B. bei HTML Chat Systemen genutzt. Ich schreibe Daten in den StreamBuffer und drücke diese dann über flush() an den Client.

    Da der Browser(Client) in der Erwartung ist das hier noch Daten kommen , da der Socket vom Server noch offen ist, hast du schon mal einen Kommunikationskanal um Daten an den Client(Browser) zu senden.

    Nun kommt JavaScript und Frames ins Spiel !
    Diesen Kommunikationskanal kann man nutzen um dem Browser ein paar Zeilen JavaScript zu senden. Da der JavaScript Interpreter des Browser diese Zeilen sofort interpretiert, kann man hierüber Daten an einen anderen Frame senden und entsprechende Events, Funktionen auslösen.

    Sagen wir du nutzt einen hidden Frame (nicht sichtbar) um hiermit (z.B. src="stream.php") den Kommunikationskanal aufzubauen.

    Im Frame den du nutzt um dem User deine Daten anzuzeigen nennen wir mal display.htm!

    Du kannst nun im Frameset einige Javascript Funktionen definieren! (z.B. push() {..da kommt was vom Server} )

    Wenn du nun in deinem Kommunikationskanal(src="stream.php")

    <script type="text/javascript">
    <!--
     parent.push("bla bla");
    //-->
    </script>

    an den Client(Browser) sendest wird die entsprechende Funktion im Frameset ausgelöst!!!

    Die Funktion könnte so aussehen:

    <script LANGUAGE="JavaScript">
    var pageStart="<HTML><HEAD></HEAD><BODY><H2>Server pushes: <P>";
    var pageEnd="</H2></BODY></HTML>";

    function push(content) {
        // zeigt im displayFrame (display.htm) die neuen Infos an !
        window.frames['displayFrame'].document.writeln(pageStart+content+pageEnd);
        window.frames['displayFrame'].document.close();
      }
    </script>

    Viel Spass beim basteln !!!! Leider habe ich wenig mit PHP am HUT und arbeite selbst mit Java und allem was dazu gehört. Aber bei der Durchsetzung mit PHP gibt es hier auch einige Profis die dir da weiterhelfen können.

    Einige wichtige Punkte noch:

    1.Der Browser arbeitet mit einem Timeout! Meint ... wenn eine lange Zeit nix vom Server mehr über diesen Socket gesendet wurde, macht der Browser den Socket dicht. Das kann dadurch verhindert werden, imdem man einen Ping sendet. Meint wiederum irgendwelche Dummydaten in bestimmten Abständen wenn keine Daten geflossen sind!

    2.Die Browser haben unterschiedliche Buffer und halten dort Daten fest bis der Buffer voll ist. Erst dann wird dieser Teil gerendert oder dem JavaScript Interpreter übergeben. Das passiert meist nur beim ersten Laden der HTML Seite. Eine einfache Lösung ist hier die Schwelle in Erfahrung zu bringen. Betroffen ist der Kommunikationskanal "stream.php" !!! Es reicht ein paar Zeilen am Anfang zu senden die ehh keiner zu sehen bekommt. ( <h1>.................... bufferkiller ....<h1> )

    Zwei drei lange Zeilen dieser Art sollten ausreichen bevor der erste JavaScript Block gesendet wird.

    2b. Wesentlich eleganter ist allerdings das senden eines Ping() ! Das wird so oft gesendet bis ein Event ausgelöst wird und der Client uns über z.B. writeln("<img src='server/ClientComIsOpen'>") signalisiert das mit dem Kommunikationskanal alles OK ist! Ebenfalls zu empf. wegen CrossBrowser bla... !

    So jetzt reichts aber ... hab keine Lust mehr ;-)

    Viel Spass beim Basteln !

    Gruesse
    code2i

    1. Paahhhhh na gut ... noch was vergessen !

      Beachten Punkt3:

      in ...stream.php hilft es mit der <META> Angabe zu arbeiten auf keinen Fall etwas im Cache abzulegen. (no-cache ?)

      Zusätzlich den entsprechenden HTTP Header Pragma = no-cache zu setzen kann auch hilfreich sein.

      Wenn es in sehr seltenen Fällen trotzdem irgendwelche Probs gibt. Werdet  schon merken was ich meine !!!! ...ist die Angabe der Dateigrösse im HTTP Header hilfreich um den stream Kanal offen zu halten.

      cu

  5. Hallo,

    Hi

    ich habe mich in den vergangenen Tagen nach chats umgeschaut, die auch ohne reloads auskommen.

    gefunden habe ich gtchat (http://www.gtchat.de/).
    der ist zwar mit perl geschrieben, aber vielleicht hilft dir das.
    beispielseiten finden sich auf der homepage unter "übersicht".
    wenn's das ist, was du brauchst, kannst du den chat ja runterladen und "auseinandernehmen" *g*

    ciao,
    steffen