tami: Websocket grunsätzlich - Variante mit PHP + Variante mit ZF2

hi alle,

http://www.sanwebe.com/2013/05/chat-using-websocket-php-socket beschreibt einen simplen Websocket-Server und -Client mit PHP/Javascript.

Das Serverscript wird schlussendlich gestartet mit:

php -q c:\path-to-server\server.php

Im Script (server.php und auch clientseite) wird noch notiert: "ws://localhost:9000/daemon.php".

Dieses "daemon.php" ist aber kein Script, das existiert, wie ich das sehe. "Was" ist das? Ein Alias für den Daemon?

Zwei Fragen, vor dem Experimentieren habe ich noch:

1. Wie stoppe ich das Script, dass ich ja über die Konsole aufrufen muss (da gibts dann wohl auch keine MaxExecutionTime)? Sicherlich kann ich über ps ax mir alle Prozesse aurufen und mit killall <Prozessnummer> dann den Prozess wieder killen, aber fragt sich, ob das der beste Weg ist. Unter Windows7 funzt die Konsole ja auch u.U. garnicht so ...; gut, da gäbe es den Taskmanager.

2. Dieser Websocket-Server ist dann für alle Clientanfragen zuständig. Die Frage ist bestimmt blöde, aber ich denke mal, dass das ja Sinn des Servers ist, alle Anfragen zu steuern. Ab welcher Fülle von Anfragen verschluckt sich dann aber das Ding?

Abgesehen davon beschäftigt mich noch: mal angenommen, es soll kein Chat damit realisiert werden, sondern zB. ein GPS-Tracker, wo der Client alle 10 Sekunden (oder auch jede Sekunde) seine Position an den Server übermittelt. Wäre da ein Socket überhaupt sinnvoll? http://www.websocket.org/quantum.html beschreibt, wie das mit den HTTP-Headern im Vergleich zu Websocktverbindung aussieht: "And what about the reduction in latency? Take a look at the following figure. In the top half, you can see the latency of the half-duplex polling solution. If we assume, for this example, that it takes 50 milliseconds for a message to travel from the server to the browser, then the polling application introduces a lot of extra latency, because a new request has to be sent to the server when the response is complete. This new request takes another 50ms and during this time the server cannot send any messages to the browser, resulting in additional server memory consumption.

In the bottom half of the figure, you see the reduction in latency provided by the WebSocket solution. Once the connection is upgraded to WebSocket, messages can flow from the server to the browser the moment they arrive. It still takes 50 ms for messages to travel from the server to the browser, but the WebSocket connection remains open so there is no need to send another request to the server." (besonders auch die Grafik dazu).

Ansonsten finde ich noch eine Variante, die auf dem ZendFramework basiert als Modul: http://modules.zendframework.com/stanislav-web/ZF2-PHP-WebSocket-Server. Hier starte ich den Server mit "php -q index.php websocket open" was nahelegt, dass ich mit dem Paramter "close" das Ding wieder schließen könnte. Allein die index.php muss ich mir selber basteln, umd das Modul zu integrieren. Da habe ich den Autor angemailt und die Antwort erhalten: "Hello, Robert!

You must initialize the application in your public index.php.

Add the following code

date_default_timezone_set('Europe/Berlin');
// Change to the current dir
chdir(dirname(__DIR__));

// Running application (that is after autiloader init)
Zend\Mvc\Application::init(require 'config/application.config.php')->run();"

Da ist mir (immer noch) nicht ganz klar, ob und wenn ja wie das entsprechende Modul dann eingebunden wird, aber da wird die Doku vom ZF vermutlich noch weiter helfen.

Wer da noch irgendwie Tipps zu hätte, wäre ich dankbar.

mfg

tami

  1. Hallo,

    Im Script (server.php und auch clientseite) wird noch notiert: "ws://localhost:9000/daemon.php".

    Dieses "daemon.php" ist aber kein Script, das existiert, wie ich das sehe. "Was" ist das?

    Eine beliebige URL auf die der Daemon reagiert. Ob das auf ein PHP-Script auflöst, ist egal, da hier ein kompletter HTTP-/Websocket-Server in PHP implementiert wird.

    Wenn ich mir den Code so ansehe, ist es völlig egal, was in der URL steht, sie wird gar nicht gelesen. Sobald ein Socket geöffnet wird, wird der Handshake gesendet. /husseldiguggeldidu würde vermutlich genauso funktionieren.

    1. Wie stoppe ich das Script, dass ich ja über die Konsole aufrufen muss

    Indem du ein SIGINT-Signal an den Prozess sendest. Z.B. indem du Ctrl + C auf dem Terminal drückst.

    Ab welcher Fülle von Anfragen verschluckt sich dann aber das Ding?

    Das hängt von verschiedenen Parametern ab und lässt sich so grob nicht sagen. Im Zweifelsfall: Benchmarken.

    Allgemein sieht diese Implementierung sehr trivial aus. Da gibt es sicher komplexere und robustere Implementierungen. (Ob in PHP weiß ich nicht.)

    Abgesehen davon beschäftigt mich noch: mal angenommen, es soll kein Chat damit realisiert werden, sondern zB. ein GPS-Tracker, wo der Client alle 10 Sekunden (oder auch jede Sekunde) seine Position an den Server übermittelt. Wäre da ein Socket überhaupt sinnvoll?

    Ja, klar. Der Overhead bei HTTP ist riesig, bei Websockets (nach dem Handshake) gering.

    Ansonsten finde ich noch eine Variante, die auf dem ZendFramework basiert als Modul: http://modules.zendframework.com/stanislav-web/ZF2-PHP-WebSocket-Server. Hier starte ich den Server mit "php -q index.php websocket open" was nahelegt, dass ich mit dem Paramter "close" das Ding wieder schließen könnte.

    Ein Blick in den Code sagt: Nein.
    https://github.com/stanislav-web/ZF2-PHP-WebSocket-Server/blob/master/Module.php
    https://github.com/stanislav-web/ZF2-PHP-WebSocket-Server/blob/master/src/WebSockets/Controller/WebsocketCLIController.php

    Der Server-Code sieht übrigens genauso aus wie aus dem einfachen Beispiel. Es gibt anscheinend keine Möglichkeit, den »sauber« herunterzufahren, nur den PHP-Prozess mit SIGINT zu schließen.

    Da ist mir (immer noch) nicht ganz klar, ob und wenn ja wie das entsprechende Modul dann eingebunden wird, aber da wird die Doku vom ZF vermutlich noch weiter helfen.

    Das ist wohl eine Zend-Framework-Frage, davon habe ich keine Ahnung. Aber es wird ja einen Grund haben, dass du die ZF-Variante gewählt hast? Also müsste dir grob klar sein, wie du es integrieren willst.

    Mathias

    1. hi molily,

      Da ist mir (immer noch) nicht ganz klar, ob und wenn ja wie das entsprechende Modul dann eingebunden wird, aber da wird die Doku vom ZF vermutlich noch weiter helfen.

      Das ist wohl eine Zend-Framework-Frage, davon habe ich keine Ahnung. Aber es wird ja einen Grund haben, dass du die ZF-Variante gewählt hast? Also müsste dir grob klar sein, wie du es integrieren willst.

      Bisher bin ich darüber nur beim Googlen gestolpert. Die Grundzüge zu kapieren, kann ja nicht schaden. Auf den ersten Blick dachte ich auch, dass das ZF da nicht "viel bringt". Außer autoload ;-).

      mfg

      tami

  2. zB. ein GPS-Tracker, wo der Client alle 10 Sekunden (oder auch jede Sekunde) seine Position an den Server übermittelt.

    http://caniuse.com/websockets beachten. Android unterstützt Websockets erst ab Version 4.4.

    Mathias

    1. hi molily,

      zB. ein GPS-Tracker, wo der Client alle 10 Sekunden (oder auch jede Sekunde) seine Position an den Server übermittelt.

      http://caniuse.com/websockets beachten. Android unterstützt Websockets erst ab Version 4.4.

      Danke für den Tipp. "Müsste" man ggfs. eine Weiche bauen ...;

      mfg

      tami

  3. Hello,

    Im Script (server.php und auch clientseite) wird noch notiert: "ws://localhost:9000/daemon.php".

    Eben nicht!
    Im Client muss schon die Domain oder IP des WS-Servers genannt werden und nicht "localhost".

    Zwei Fragen, vor dem Experimentieren habe ich noch:

    1. Wie stoppe ich das Script, dass ich ja über die Konsole aufrufen muss (da gibts dann wohl auch keine MaxExecutionTime)? Sicherlich kann ich über ps ax mir alle Prozesse aurufen und mit killall <Prozessnummer> dann den Prozess wieder killen, aber fragt sich, ob das der beste Weg ist. Unter Windows7 funzt die Konsole ja auch u.U. garnicht so ...; gut, da gäbe es den Taskmanager.

    Bei Linux mit KILL. Da kannst Du den Prozess auch in den Hintergrund stellen mit

    ./server.php &

    Du solltest Dir also die PID merken oder besser noch, in einem PID-File speichern.

    Unter Windows erstmal mit CTRL-C. Da der Server ja (Fehler-)Ausgaben über die Standardausgabe erzeugt, lauscht er auch auf das Break-Flag. Das CMD-Fenster ist daher auch solange für den Server reserviert, wie er läuft.

    1. Dieser Websocket-Server ist dann für alle Clientanfragen zuständig. Die Frage ist bestimmt blöde, aber ich denke mal, dass das ja Sinn des Servers ist, alle Anfragen zu steuern. Ab welcher Fülle von Anfragen verschluckt sich dann aber das Ding?

    Das ist erstmal nur eine Rumpfidee.
    Der bedient alle Anfragen, die auf diesem Port eintrudeln. Da Du ja wahrscheinlich mehrere VirtHosts auf deinem Server hast, würde er also quer über die HTTP-Virt-Hosts die TCP-Anfragen (Websocket) auf dem Port bedienen. Das wäre natürlich unpraktisch.

    Ansonsten finde ich noch eine Variante, die auf dem ZendFramework basiert als Modul: http://modules.zendframework.com/stanislav-web/ZF2-PHP-WebSocket-Server. Hier starte ich den Server mit "php -q index.php websocket open" was nahelegt, dass ich mit dem Paramter "close" das Ding wieder schließen könnte. Allein die index.php muss ich mir selber basteln, umd das Modul zu integrieren. Da habe ich den Autor angemailt und die Antwort erhalten: "Hello, Robert!

    Das muss ich mir auch noch mal ansehen.

    Liebe Grüße aus dem schönen Oberharz

    Tom vom Berg

    --
     ☻_
    /▌
    / \ Nur selber lernen macht schlau
    Die ultimative Seite für Selbermacher
    1. hi Tom,

      ich kann nur sagen: bei mir "funzt" es ...;

      mfg

      tami

      1. Hello,

        hi Tom,

        ich kann nur sagen: bei mir "funzt" es ...;

        Mit mehreren Clients im Netz?
        Kann ja gar gar nicht!

        siehe https://forum.selfhtml.org/?t=217753&m=1496800

        Liebe Grüße aus dem schönen Oberharz

        Tom vom Berg

        --
         ☻_
        /▌
        / \ Nur selber lernen macht schlau
        Die ultimative Seite für Selbermacher
        1. hi Tom,

          Hello,

          hi Tom,

          ich kann nur sagen: bei mir "funzt" es ...;

          Mit mehreren Clients im Netz?
          Kann ja gar gar nicht!

          Na, die IP von dem Rechner, mit dem man sicher verbinden will, muss schon stimmen, bzw. dessen Domain. Ob das nun ws: oder http: ist, ist ja egal. Mit 127.0.0.1 bleibst du, wo du bist ;-).

          http://wordpress.wvs-berlin.de/?p=1414: "Das Clientscript musste angepasst werden (statt localhost die IP 10.31.255.135) bzw. in Gänze: “ws://10.31.255.135:9000/~rob/websocketchat/server.php”. Ob der komplette Pfad zum Server allerdings notwendig ist, weiß ich nicht. Der Port alleine und die IP müssten eigentlich reichen."

          mfg

          tami