• Das Erstellen neuer Accounts wurde ausgesetzt. Bei berechtigtem Interesse bitte Kontaktaufnahme über die üblichen Wege. Beste Grüße der Admin

[FRAGE] Clients refreshen

huberlix

New member
Kann ich über eine PHP-Datei alle Clients refreshen (Noch besser nur einen bestimmten User)?

Hoffe, ich kann euch das einigermaßen erklären, um was es geht, ohne euch zu verwirren.

Ich habe auf meiner HTML-Seite eine Tabelle, die dynamisch generiert wird.
Zunächst muss sich jeder User identifizieren (es gibt nur ca 25 User). Dann wird "User" im LocalStorage gespeichert. Beim aufbau der Tabelle hat dann jeder User seine individuelle Tabelle.

Die Tabelle wird in "Pagebeforeshow" dynamisch erstellt. Zunächst mit lauter Nullen.
Per "addRowHandlers()" wird das Onclick-Event zugefügt.

Nun kann man auf eine Zelle klicken und im folgenden Dialog einen Wert eintragen. Dieser wird im Localstorage gespeichert, und gleichzeitig per PHP in einer JSON-Datei.
Wenn der Dialog schließt, wird "Pagebeforeshow" wieder ausgelöst, und die Tabelle mit neuem Wert (aus Localstorage) neu aufgebaut.

D.h.: Jeder sieht seine eigene Tabelle, mit Werten aus Localstorage. Gleichzeitig werden die Werte von allen in der JSON-Datei gespeichert, um die Werte vergleichen zu können.

Nun möchte ich das ganze farblich markieren. Es geht um die Eintragung von Geldbeträgen.
Beispiel: User1 muss an User2 1,00€ zahlen. Nun trägt User1 -1,00€ ein, und User2 +1,00€.

Vor Aufbau der Tabelle wird die JSON-DATEI runtergeladen, und die Werte verglichen.
Steht bei beiden das gleiche (Bei einem -, beim anderen +, vergleiche ich mit "if user1+user2==0" --> Zelle grün.
Hat nur einer was eingegeben, der andere noch nicht, "if user1 + alterWert(user2)==0)" --> Zelle gelb.
Wurde ein falscher Wert eingegeben, --> Zelle rot
Funktioniert auch soweit. Aber in der Praxis gibt es folgendes Problem:

Szenario:
User1 (-1,00) - User2 (+1,00) --> beide Zellen grün.
Nun muss User1 80ct zahlen.
User1 gibt -0,80 ein. User2 hat noch nichts eingegeben.
Bei User1 wird die Tabelle neu aufgebaut, Zelle gelb, da der alte Wert noch mit User2 übereinstimmt.

Aber bei User2 ist immer noch grün! Wenn der vergisst den Wert einzugeben, bleibt das auch so.
Hier bräuchte ich einen Routine, die beim hochladen von User1 auf die PHP, gleichzeitig bei allen (besser nur bei User1) ein Refresh macht.

Ist das irgendwie machbar?

http://Hier könnt ihr sehen um was es geht. Beim ersten mal einen Namen (außer Fedi und Roko) auswählen, weil ich diese User zu Testzwecken benutze.
Farben könnt ihr auch nur sehen, wenn ihr zahlungen mit Fedi oder Roko vornehmt, weil es sonst z.Z. keine User gibt. (In der JSON-Datei sind wird gespeichert, wer aktiver Nutzer ist).

Auf den ersten Zahlenwert in der Tabelle klicken zum eintragen!
 
Stimmt, unser aller Freund der IE macht da wieder nicht mit bei dem Game :(
Bin froh, dass wir Chromium-Applications bauen und nicht auf den tollen IE angewiesen sind :D
 
Zuletzt bearbeitet:
Bin froh, dass wir Chromium-Applications bauen
um gottes willen! bin gespannt wann der große knall kommt, weil rauskommt, dass google über den chrome intime, vertrauliche und persönliche daten gesammelt hat, die gestohlen wurden. mir ist die marktdominanz ein riesen keil im auge.
 
um gottes willen! bin gespannt wann der große knall kommt, weil rauskommt, dass google über den chrome intime, vertrauliche und persönliche daten gesammelt hat, die gestohlen wurden. mir ist die marktdominanz ein riesen keil im auge.

Wahre Worte und er frisst RAM wie bekloppt, aber dafür kann er alles - ist halt die Entscheidung zwischen Pest und Cholera :D
 

Danke an alle, werd mir alle Ansätze die Tage mal durchlesen. Hab grad im Moment wenig Zeit dafür.
SSE klingt zunächst mal einfach und vielversprechend.

1.)
Würde ich dann den "Empfangscode"
Code:
var source = new EventSource("demo_sse.php");
source.onmessage = function(event) {
    document.getElementById("result").innerHTML += event.data + "<br>";
};

im $(document).on("pageshow"............ der zu refreshenden Seite einfügen?

Oder irgendwo im Java-Script?
Und stett document.getElementById("result").innerHTML += event.data + "<br>"; einfach Page(X).refresh() (Nicht am Syntax aufhängen! Hab ich jetzt ganz frei dahingeschrieben)?


2.)
Code:
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');

$time = date('r');
echo "data: The server time is: {$time}\n\n";
flush();
?>

kann dann dieser Code auch in meiner "Update.php" verwendet werden? Also sobald in das File geschrieben wird, den Event senden?
Muss ich dann ein leeres echo "data: " senden, oder eher echo "data: blabla"? Und dann
Code:
source.onmessage = function(event) {
    if (event.data =="blabla") .....refresh.....



Sorry, von php hab ich gar keine Ahnung.
 
Hmmm, krieg jetzt in der Konsole folgende Fehlermeldung: Firefox kann keine Verbindung zu dem Server unter http://www.huberlix.de/Test/update.php aufbauen.
Später, wenn die PHP in meine JSON-Datei schreibt, hab ich verbindung!


Hab meine PHP wie folgt geändert:
Code:
 <?php 
	header('Content-Type: text/event-stream');
	header('Cache-Control: no-cache');
    if(isset($_POST)) {
        $message = $_POST['message'];
        $file = $_POST['file'];
        header("Refresh:0");
        if(file_put_contents($file, $message)) {
            echo 'Die Nachricht "'. $message . '" wurde erfolgreich in "' . $file . '" geschrieben!';
        } else {
            echo 'Fehler beim schreiben in ' . $file . '!';
        }    
    }
	

   $time = date('r');
   echo "data: The server time is: {$time}\n\n";
   flush();
?>

Und im body der HTML den Script:

Code:
   <body>
<script>
   if(typeof(EventSource) !== "undefined") 
   {
	   var source = new EventSource("update.php");
	   source.onmessage = function(event) 
	   {
		   document.getElementById("result").innerHTML += event.data + "<br>";
	   };
   } else 
   {
    document.getElementById("result").innerHTML = "Sorry, your browser does not support server-sent events...";
   }
</script>
 
Die update.php sollte selber auf keinen Fall irgendwelche Daten annehmen/schreiben - die ist nur dazu da, Daten zum Client zu schicken. Auch darf die nicht komplett durchlaufen - schau' dir mal das Beispiel au MDN an: https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events

Das verwirrt mich jetzt ein bißchen.
Die update.php ist ursprünglich nur dazu da, Daten anzunemen/schreiben. Sie soll mir Daten in die "Daten.json" schreiben.

Heißt das, das Event muss in einer neuen php gesendet werden?
Die Idee war ja, wenn Daten in die "Json" geschrieben werden, soll das Event ausgelöst werden.

Oder reden wir aneinander vorbei?
 
Heißt das, das Event muss in einer neuen php gesendet werden?
Ja - das Eventscript läuft ja dauernd und hält das Socket offen, damit die Events gesendet werden können.

Die Idee war ja, wenn Daten in die "Json" geschrieben werden, soll das Event ausgelöst werden.
Dann musst du irgendeine Art von Kommunikation zwischen den beiden Skripten auf dem Server etablieren.

PHP/Apache ist für solche Sachen sowieso nicht besonders gut geeignet, da es in diesem Fall sehr schlecht skaliert. Mit Nodejs wäre so etwas viel einfacher.
 
So, hab jetzt mal folgendes probiert.

JSON Datei wird runtergeladen, und die Daten modifiziert.
Danach via "update.php" wieder hochgeladen.

Direkt danach die 3 geänderten Werte (aktiver User, Gegner, Wert) als Array zur "refresh.php" übergeben.

Wenn ich im Browser (FF) "Element untersuchen", "Netzwerk" --> refresh.php -->Antwort untersuche, kommt "Data: Array" zurück. Scheint also zu funktionieren.

Kann ich nun im Javascript auf das Event reagieren? Das problem dabei ist, es soll ja bei einem anderen User als der Sender reagiert werden. Im Moment fange ich das Event im "Success"-Teil beim hochsenden in die refresh-Datei ab. Kann natürlich nicht funktionieren, da der, der es empfangen soll, nicht der Sender ist.

Fange ich das Event direkt am Anfang der JS-Datei ab (außerhalb aller Page-show/beforeshow... Events) passiert nix.
Beim User, der das Event empfangen soll, ist ja die Seite fertig geladen.
Wo muss ich das Event abfangen?


JS:
Code:
$.getJSON('Daten.json', function(daten) /* JSON-Datei laden */
   {	
	 
	  daten[user][zelle[0].innerHTML]=werte[0]; 	 /* JSON-Daten verändern*/
	  daten[user]["Benutzer"]=true;
	  
	  $.ajax(         /*und wieder hochladen*/
	  {
		 type: "POST",
		 url: 'update.php',
		 data: {message :JSON.stringify(daten), file: 'Daten.json'},  
		 success: function(data)
		 {
			/* alert(data);*/
		 },		   
		 error:function()
		 {
			 /*alert("es ist ein Fehler aufgetreten");*/
		 }
	  });
	  
	  $.ajax(          /* Refresh-Datei aufrufen mit und geänderte Werte übergeben */
	  {
		 type: "POST",
		 url: 'refresh.php',
		 data: {message :[user, zelle[0].innerHTML,werte[0]]}, /* 3 geänderte Werte als Array übergeben */
		 success: function(data)
		 {
			if(typeof(EventSource) !== "undefined") 
			{
			   var source = new EventSource("refresh.php");
			   source.onmessage = function(event) 
			   {
				 document.getElementById("result").innerHTML += event.data + "<br>";
			   };
			} 
			else 
			{
			   document.getElementById("result").innerHTML = "Sorry, your browser does not support server-sent events...";
			}
		 },		   
		 error:function()
		 {
			 /*alert("es ist ein Fehler aufgetreten");*/
		 }
	  });
				  
   });

Refresh.php:
Code:
 <?php 
	header('Content-Type: text/event-stream');
	header('Cache-Control: no-cache');
   $message = $_POST['message'];

   
   echo "data: $message";
   flush();
?>

update.php:
Code:
 <?php 
	
    if(isset($_POST)) {
        $message = $_POST['message'];
        $file = $_POST['file'];
        header("Refresh:0");
        if(file_put_contents($file, $message)) {
            echo 'Die Nachricht "'. $message . '" wurde erfolgreich in "' . $file . '" geschrieben!';
        } else {
            echo 'Fehler beim schreiben in ' . $file . '!';
        }    
    }
?>

- - - Aktualisiert - - -

Vielleicht nochmal zur Erklärung:
Die Werte schicke ich nur zur Refresh-Datei, damit diese wieder zurückgesendet werden, und ausschließlich der Gegner darauf reagiert.

Wenn das nicht geht, könnte ich auch die Refresh ohne Daten aufrufen, um dann einfach bei "Onmessage" alle Browser zum neu laden bewege.

- - - Aktualisiert - - -

Hab nochmal versucht es im HTML direkt am Anfang des "body" abzufangen, auch da passiert nix.

HTML:
   <body>
<script>
			if(typeof(EventSource) !== "undefined") 
			{
			   var source = new EventSource("refresh.php");
			   source.onmessage = function(event) 
			   {
				 alert(event.data);
			   };
			} 
			else 
			{
			   document.getElementById("result").innerHTML = "Sorry, your browser does not support server-sent events...";
			} 
</script>
 
Ich raffs einfach nicht.
Ich hab jetzt eine ganz einfache Site aufgebaut, mit eben nur dem SSE-Eventhandler.
Das Komische: Die "refresh.php" wird 2X aufgerufen. Beim 1. mal ok, Beim 2.mal "Firefox kann keine Verbindung......"

Hier mein JS-Code:
Code:
$(document).on( "pagebeforeshow", "#home",function(event) 
{
   if(typeof(EventSource) !== "undefined") 
   {
	  var source = new EventSource('refresh.php');    [COLOR="#FF0000"]  /*Hier entsteht die Fehlermeldung*/[/COLOR]
	  /* source.onmessage = function(e) 
	  {
	  $("#content").innerHTML = "Geht";
	  };*/
	  source.addEventListener("message", function(e) 
	  {
		 document.getElementById("content").innerHTML += e.data + "<br>";
	  });
   } 
   else 
   {
	  $("#content").text = "Geht nit";
   } 
});

Hier mein HTML:
HTML:
<!DOCTYPE html>
<html>
   <head>
      <meta name="viewport" content="width=device-width , initial-scale=1">
      <meta charset="utf-8">
      <link rel="stylesheet" href="https://code.jquery.com/mobile/1.3.0/jquery.mobile-1.3.0.css">
      <script src="https://code.jquery.com/jquery-1.9.1.js"></script>
      <script src="scripts/eigene.js"></script>
      <script src="https://code.jquery.com/mobile/1.3.0/jquery.mobile-1.3.0.js"></script>
    
   </head>
   
   <body>
      <div data-role="page" data-theme="d" id="home">  
      
         <div data-role="header" id="header" data-position="fixed">            
            <h1 class="ui-title" role="heading">Test</h1>            
         </div>
         
         <div data-role="content" id="content" class="content"></div>
         
         <div data-role="footer" data-position="fixed"></div>
      </div>     
   </body>
</html>


Und hier die Meldung der Konsole:
Code:
GET http://www.huberlix.de/abc/                                                                                                                [HTTP/1.1 304 Not Modified 41ms]
GET https://code.jquery.com/mobile/1.3.0/jquery.mobile-1.3.0.css                                                                    [HTTP/2.0 304 Not Modified 13ms]
GET http://ff.kis.v2.scr.kaspersky-labs.com/40BF9406-C8E2-D84E-BBAE-1985760E9E5D/main.js                              [HTTP/1.1 200  5ms]
GET https://code.jquery.com/jquery-1.9.1.js                                                                                                 [HTTP/2.0 304 Not Modified 13ms]
GET http://www.huberlix.de/abc/scripts/eigene.js                                                                                          [HTTP/1.1 200 OK 35ms]
GET https://code.jquery.com/mobile/1.3.0/jquery.mobile-1.3.0.js                                                                      [HTTP/2.0 304 Not Modified 13ms]
GET https://code.jquery.com/mobile/1.3.0/images/ajax-loader.gif                                                                      [HTTP/2.0 304 Not Modified 16ms]
[COLOR="#008000"]GET XHR http://www.huberlix.de/abc/refresh.php                                                                                          [HTTP/1.1 200 OK 54ms][/COLOR]
[COLOR="#FF0000"]Firefox kann keine Verbindung zu dem Server unter http://www.huberlix.de/abc/refresh.php aufbauen.                     eigene.js:5:19[/COLOR]
GET http://ff.kis.v2.scr.kaspersky-labs.com/40BF9406-C8E2-D84E-BBAE-1985760E9E5D/websocket                        [HTTP/1.1 101  2ms]
GET https://code.jquery.com/mobile/1.3.0/jquery.mobile-1.3.0.css                                                                    [HTTP/2.0 200 OK 0ms]
 
Deine refresh.php ist immer noch falsch aufgebaut. Die muss ja immer laufen, solange die Verbindung offen ist. Also du musst in PHP im Grunde genommen eine Event-Loop bauen, die Nachrichten schickt, falls irgendwas passiert.
 
Hmm, auch auf die Gefahr hin, dass ich jetzt langsam nerve :rolleyes:

Wenn ich das richtig gelesen habe, öffnet der Browser alle paar sekunden die Verbindung, und die php wird erneut ausgeführt.
"Firefox kann keine Verbindung...." hab ich jetzt weg. Wieso auch immer.
Habe mit dem Servertime-Beispiel aus dem Netz mal ganz neu angefangen, und auf meine Bedürfnisse umgeändert.

Wenn ich in der php die Variable $message direkt definiere mit $message ='irgendwas'; , kriege ich im Browser folgende Ausgabe:
irgendwas
irgendwas
irgendwas
....
....
ca alle 5 sekunden ne neue Zeile.

Übergebe ich der Variablen allerdings den hochgesendeten Parameter $message =$_POST['message']; , passiert nix.
Allerdings wenn ich im Firefox "Element untersuchen--Netzwerk--Antwort" anschaue, krieg ich da "data: Testmessage" angezeigt. Also wird doch $message mit dem Parameter geladen. Warum "flushed" das nicht?

PHP:
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');

 if(isset($_POST))
 {
   $message =$_POST['message']; 
   
   echo "data: $message";
   
   flush();   
 }
?>

Code:
$(document).on( "pageshow", "#home",function(event) 
{
   if(typeof(EventSource) !== "undefined") 
   {
	  var source = new EventSource("refresh.php");
	  source.onmessage = function(e) 
	  {
		 document.getElementById("result").innerHTML += e.data + "<br>";
	  };
   } 
   else 
   {
	  document.getElementById("result").innerHTML = "Sorry, your browser does not support server-sent events...";
   }
   $.ajax( 
   {
	  type: "POST",
	  url: 'refresh.php',
	  data: {message :'Testmessage'}, 
	  success: function(data)
	  {
		 
	  },		   
	  error:function()
	  {
		  /*alert("es ist ein Fehler aufgetreten");*/
	  }
   });  
});
 
Warum bist du der Meinung, dass dein AJAX-Request irgendwie deine SSE beeinfluss? Das sind zwei verschiedene HTTP-Requests, die nichts miteinander zu tun haben.

Auch ist deine refresh.php immer noch falsch. Hast du dir den Link in #11 wirklich durchgelesen? Da ist eine nicht endende Schleife im PHP...
 
In #11 nehme ich an, die While-Schleife dient dazu, jede 1Sekunde einen Ping zu senden.
Tatsächlich ist eine Endlosschleife nicht nötig. siehe Beispiel https://www.w3schools.com/html/html5_serversentevents.asp

var source = new EventSource("refresh.php");
source.onmessage = function(e)

sorgt scheinbar dafür, das bei beendeter Connection nach ca 5 sec wieder eine Connection aufgebaut wird.
Auch ohne Endlosschleife wird tatsächlich alle 5 sek. Endlos die Servertime gesendet.

Bin aber der Lösung auf der Spur:

Wenn ich $message in der php mit einem festen Wert belege, funktionierts ja. Untersuche ich dann "Netzwerk", wird die php
einmal mit "GET" aufgerufen, --> das erste mal source = new EventSource,
dann einmal mit "POST" --> mein hochladen der Variablen -- $.ajax({type: "POST", url: 'refresh.php', data: {message:'Testmessage'}.................
Danach immer wieder mit "GET" --> Alle 5 sek. reconnection.

Nur bei "POST" kann ich in "Antwort" meine Variable auslesen. Es wird scheinbar nur bei "GET" zum Server gestreamt.

Hab schon ne Idee wie ich das löse. Werde berichten.

- - - Aktualisiert - - -

OK, die Endlosschleife hält meine Connection offen, und es muss nicht ständig reconnected werden. Ist das ein Vorteil? Welcher?

Ist es Serverseitig denn kein Problem, wenn ein Programm endlos bis ins nächste Jahrhundert durchläuft?
 
Zuletzt bearbeitet von einem Moderator:
In #11 nehme ich an, die While-Schleife dient dazu, jede 1Sekunde einen Ping zu senden.

Tatsächlich ist eine Endlosschleife nicht nötig.
bei verbindungsabbruch wird intern im browser diese neu aufgebaut.
das ist nichts anderes als ein long polling request oder ein zyklischer ajax-request(je nachdem ob du das php-script beendest oder nicht), nur dass sich der browser drum kümmert. gerade long polling requests waren ja nicht einfach zu handhaben.

Untersuche ich dann "Netzwerk", wird die php
einmal mit "GET" aufgerufen, --> das erste mal source = new EventSource,
dann einmal mit "POST" --> mein hochladen der Variablen -- $.ajax({type: "POST", url: 'refresh.php', data: {message:'Testmessage'}
was 2 verschiedene sachen sind.

Danach immer wieder mit "GET" --> Alle 5 sek. reconnection.
nur wenn du das so machst

Nur bei "POST" kann ich in "Antwort" meine Variable auslesen. Es wird scheinbar nur bei "GET" zum Server gestreamt.
nur bei dem ajax post übergibst du ja die message, du kannst zwar auch beim get request parameter mitgebenvar source = new EventSource("refresh.php?message='Testmessage'")
aber das wäre ja unsinnig.

du musst ja 2 sachen erledigen
* den client/die clients benachrichtigen, wenn ein ereigniss auf dem server eintrifft
* das ereigniss auf dem server auslösen

punkt 1 ist dein sse und punkt 2 dein ajax post. wenn du daten beim ereigniss mitgeben willst, musst du diese auf dem server speichern. z.b. in einer datenbank.
du musst also im serverscript welches für punkt 1 zuständig ist einen datenbank eintrag abfragen und wenn sich da was ändert diesen an den client senden.
außerdem musst du im serverscript welches für punkt 2 zuständig ist die daten in die datenbank eintragen und evtl. noch irgendein flag setzen, dass neue daten da sind welches serverscript1 abfragen kann.

OK, die Endlosschleife hält meine Connection offen, und es muss nicht ständig reconnected werden. Ist das ein Vorteil? Welcher?
du musst dich entscheiden, willst du ständig den server belasten mit verbindungsaufbauten oder mit laufenden/wartenden prozessen und offenen verbindungen.
beides ist nicht schön, es gibt also nur den vorteil, dass der jeweilige nachtel durch einen anderen ersetzt wird.

Ist es Serverseitig denn kein Problem, wenn ein Programm endlos bis ins nächste Jahrhundert durchläuft?
das willst du ja aber erreichen mit sse, ein problem ist das natürlich schon, außerdem bleibt für jeden client eine verbindung offen, andererseits ist ein ständiger verbindungsaufbau auch ein problem für den server
 
Zurück
Oben