PHP Web Socket für Raspi

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • HI Leute

    Ich bastle mir gerade ein eigenes Messgerät mit dem guten Raspi und jetzt bin ich an nem Punkt angelangt wo ich auf zusätzliche Hilfe angewiesen bin.

    Zum Hintergrund:
    Das gute Stück soll irgendwann Vierpole messen und die MEsskurven dann irgendwie grafisch aufbereiten. Da ich Platformunabhängig bleiben möchte und das Messergebniss gegebenfalls auf dem Smartphone im Warmen (Antennenmessung) ansehen möchte kam ich sofort zu der Lösung irgendwas mit Webinterface. Da die Daten, aber relativ schnell aktualisiert werden sollen, bin ich auf den Websocket gekommen um mir die MEssdaten vom Rasp auf das Endgerät zu streamen.

    Nun komme ich auf den Punkt meines Problems.
    Ich habe es bereits zusammengebracht, eine server.php zu schreiben welche ich dann in der shell mit php -q C:/xampp/htdocs/rasp/server.php starte.
    Der Client ladet dann quasi eine index.html mit einem JavaScript CodeSchnipsel, der die Verbindung dann aufbaut.
    Nun schaffe ich es ja schon über das Handshake, was schon ein kleiner brocken war. Jetzt kommt aber der Hund: Sobald ich vom Server eine Nachricht schicken möchte, kommt am Client nichts an.

    Hier sind die relevanten Codeteile:

    Server.php


    Und hier noch die index.html mit dem Ausschnitt aus dem JavaScript-Code:


    Ich habe mir alle möglichen Dinge ausgeben lassen, hab an der Formatierung des zu sendenden Strings gefeilt aber da geht nichts.

  • Ich glaube nicht das die server.php in der Form funktionieren wird, insbesondere weil php nach einer gewissen "max executing time" beendet wird.

    Aber auch der Aufruf

    Code
    var connection = new WebSocket('ws://192.168.1.101:5000/rasp/server.php');

    sieht ziemlich seltsam aus. Die server.php wird zu dem Zeitpunkt noch gar nicht ausgeführt und somit kann auf Port 5000 noch nichts lauschen - falls doch dann macht der Aufruf "/rasp/server.php" aber ebenfalls kein Sinn. Also wenn dann nur eins von beidem.

    Aber wie gesagt bezweifel ich das die server.php wirklich länger als 120 Sekunden laufen wird, die Verbindung also irgendwann zwangsgetrennt wird.
    Die "while (True)" macht so aber auch kein Sinn, weil bei jedem Durchlauf gar nicht darauf geachtet wird ob ein Client überhaupt connected ist, es wird einfach angenommen aber genau das ist fatal.

    Aber der wahrscheinlich größte Fehler ist dass WebSocket nicht kompatible zu Socket ist. Ein WebSocket verwendet HTML-Header für den Handshake, aber ein normaler Socket versteht das nicht wirklich.
    Dieses Problem hatte ich in meinem Projekt auch (siehe 1.Link in meiner Signatur), woraufhin ich letztlich auf Python-Tornado statt normalem Socket aufbauen musste um mit WebSocket umgehen zu können...

  • Die Sache ist aber die folgende.
    Teile aus meinem Script stammen aus einem Chat-Script (Link muss ich nochmal suchen) Dieses Script habe ich dann eifnach der Gaude-halber getestet und das hat funktioniert, auch über die 120 Sekunden hinweg. Es wurde also nicht abgebrochen wie schon so oft mir gesagt wurde. Derzeit läuft ja auch das ganze XAMPP Paket auf meinem Test-PC, wodurch ich eben die Server.php mit der Shell aufrufe die beim XAMPP dabei ist.

    php -q C:/xampp/htdocs/rasp/server.php


    Die Testausgaben die im Server.php File enthalten sind, stimmen auch datsächlich überein. Sprich die ausführungen wurden mit socket_last_error und socket_strerror überprüft und da kamen keine Fehlermeldungen.

    Wenn ich in die on.close() ein Alert einbaue, wird dieses auch beim Beenden des Servers sofort ausgeführt...auch nach einer Laufzeit von über 120 sekunden.

  • Ausführung eines PHP Scripts über die Konsole ist etwas anderes als über den Apachen. Für gewöhnlich kann man die "max executing time" auch hoch setzen oder explizit abschalten, richtig. Standardmäßig ist es aber auf 120 Sekunden eingestellt.

    Aber dein Hauptproblem ist die Art deines Aufrufs die so gar kein Sinn ergibt:

    Code
    var connection = new WebSocket('ws://192.168.1.101:5000/rasp/server.php');

    ..ich wiederhole mich ungerne, die Begründung nannte ich bereits oben:

    Wenn, dann muss die server.php vorher ausgeführt werden und der Aufruf über dein Javascript sähe dann so aus:

    Code
    var connection = new WebSocket('ws://192.168.1.101:5000');

    Es macht an dieser Stelle aber ebenfalls gar keinen Sinn den Aufruf wie folgt aussehen zu lassen:

    Code
    var connection = new WebSocket('ws://192.168.1.101/rasp/server.php');

    Weil dann kein Socket verwendet werden kann, da der Socket erst auf einem bestimmten Port initialisiert wird und WebSocket auf ^diese Art keine (KEINE) Verbindung dort hin herstellen kann.

    Auf dem Port 5000 läuft nichts solange die server.php nicht ausgeführt wird. Der WebSocket kann aber erst eine Verbindung herstellen wenn der Socket auf Port 5000 fertig initialisiert wurde.


    Und ich wette mit dir dass das Chat-Script den Aufruf anders geregelt hat - da ich das aber nicht kenne kann ich dazu nix genaueres sagen.

  • Hi

    Also herzlichen Dank einmal für deine Hilfeleistung. Weiß ich zu schätzen.

    Hier ist einmal der Link von dem Chat-Script, dass ich zum laufen gebracht habe.
    http://www.sanwebe.com/2013/05/chat-u…cket-php-socket

    Dass der Server zuerst gestartet werden muss, bevor ein Client dazu verbinden kann ist mir klar. deswegen habe ich bereits vorher glaub ich erwähnt, dass ich zuerst den Server via Shell starte. Anschließend den Browser öffne und die Ziel-IP in meine Adressleiste eingebe, öffnet sich auch die index.html

    Ich gelange auch in die connection.onopen hinein, kann mir mit einem Alert dies auch anzeigen lassen. connection.onclose funktioniert auch einwandfrei, sobald ich die Shell beispielsweise schließe und somit der Server nichtmehr läuft. Auch die connection.onerror wird aufgerufen, sobald der Server nicht erreichbar ist.

    Einzig die connection.onmessage schaffe ich nicht, dass sich die bei einer eingehenden Nachricht des Servers aufruft. Das ist quasi nurmehr der einzige Fehler der mir hier auffällt.


    So am Rande gedacht: Was würdest du denn deiner meinung nach als Lösungsansatz nehmen?
    (Ich habe nämlich Websockets über PHP gewählt, weil das die einzige Programmiersprache im Netz ist, die ich irgendwie beherrsche)


    Als Attachment habe ich noch zwei Screenshots von der Console und der Shell gemacht, falls da jemand was herrauslesen kann und etwas versteht.


    PS: Ich habe nun die von dir vorgeschlagene Änderung vorgenommen. IM JavaScript steht nun die Definition des WebSocket so wie du es vorgeschlagen hast. Die Funktion connection.onmessage startet aber trotzdem nicht. Stattdessen haben sich bei den Ereignissen in der Browserconsole die Statusinformationen geändert. nun steht statt dem 304 Error ein 200 OK Status. Dürfte sich also tatsächlich etwas getan haben. Dennoch schaffe ich es aber nicht mit socket_write oder mit socket_send etwas vom Server zum Client zu schicken. Was ja dann den Aufruf der connection.onmessage zufolge haben sollte.

  • 1. Sry für den Doppelpost

    2. Ich habe die Lösung für mein Problem gefunden. Mit PHP können durchaus WebSockets programmkiert werden. Das starten der server.php ist gegen alle Behauptungen tatsächlich auf keine Laufzeit beschränkt. Und die Lösung war, dass das Datenpaket, welches an den Server geschickt werden kann zunächst maskiert werden muss, damit es nachher auf die Reise geschickt werden muss. Porgrammcode ist nicht meiner, wems interessiert:

    [code=php]

    //Encode message for transfer to client.
    function mask($text)
    {
    $b1 = 0x80 | (0x1 & 0x0f);
    $length = strlen($text);

    if($length <= 125)
    $header = pack('CC', $b1, $length);
    elseif($length > 125 && $length < 65536)
    $header = pack('CCn', $b1, 126, $length);
    elseif($length >= 65536)
    $header = pack('CCNN', $b1, 127, $length);
    return $header.$text;
    }

    [/php]

    Hat nun gefruchtet und funktioniert einwandfrei. Projekt wird also fortgesetz und nun werden mal die Daten aus einem Text-Dokument ausgelesen. Anschließend wird dann, sofern das Auslesen funktioniert hat, die Hardware ausgelesen, statt einem Text-Dokument.

    Danke für die Hilfe

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!