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

[GELÖST] Server Sent Event sendet immer nur an einen Client

huberlix

New member
Wer hilft mir mal mit den SSE weiter. Bin am verzweifeln.

Server-Code:
PHP:
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
$altezeit=1508857791;    //hier wird nur ne Zeit gesetzt, die auf jeden Fall vor der aktuellen liegt.
while (1) 
{     
   $filename = 'Daten.json';
   if (file_exists($filename)) 
   { 
	  $neuezeit=filemtime($filename);
	  var_dump($neuezeit);
   }
   if ($neuezeit>$altezeit)   //Wenn Timestamp neu, SSE senden
   {
	  $altezeit=$neuezeit;
	  $h = fopen('Daten.json', 'r+');
	  if (flock($h, LOCK_EX)) 
	  { 	  
		 $jsondata=file_get_contents('Daten.json');		//Hier werden nur die Json-Daten decodiert und dann gesendet
		 $obj=json_decode($jsondata);				   
		 echo "data: $jsondata\n\n";		 
		 @ob_end_flush();
		 @flush();
		 $obj->update = false;	  
		 fseek($h, 0);
		 ftruncate($h, 0);
		 fwrite($h,json_encode($obj)); 		 
	  }	
	  flock($h, LOCK_UN);  
	  fclose($h);
   }
   sleep(1);
}
?>

Client-Code:
Code:
$(document).on( "pagebeforeshow", "#home",function(event) 
{
   var evtSource = new EventSource("refresh.php");
   evtSource.onmessage = function(e)
   {
	 
	  var Data=JSON.parse(e.data);
	  alert(e.data);
.............
.............

Ich teste im Moment mit 3 verschiedenen Clients.
Auf Desktop Firefox und Safari,
und Iphone mit Safari.

Wenn ich ein SSE auslöse (Indem ich die Datei Daten.json verändere), kommt es immer nur an dem Browser an, der das SSE ausgelöst hat.
Die beiden anderen Clients bleiben stumm.

Woran kann das hängen?
Der Event-Listener ist doch auf allen Clients aktiv!?


Gruß Bernd
 
Zuletzt bearbeitet von einem Moderator:
Hast recht. Ich habs geändert:
PHP:
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
$altezeit=1508857791;
while (1) 
{     
   $filename = 'Daten.json';
   if (file_exists($filename)) 
   { 
	  $neuezeit=filemtime($filename);
	  var_dump($neuezeit);
   }
   if ($neuezeit>$altezeit)
   {
	  
	  $h = fopen('Daten.json', 'r+');
	  if (flock($h, LOCK_EX)) 
	  { 	  
		 $altezeit=$neuezeit;
		 $jsondata=file_get_contents('Daten.json');		
		 $obj=json_decode($jsondata);				   
		 echo "data: $jsondata\n\n";		 
		 @ob_end_flush();
		 @flush();			 
	  }	
	  flock($h, LOCK_UN);  
	  fclose($h);
   }
   sleep(1);
}
?>

Allerdings mit dem Problem hat das nix zu tun.
Ich geh davon aus, das Problem ist der Zeitpunkt, wann der Event-Listener seine function ausführt.

Im Moment in Pagebefore. Ich denk, der Client, der die Änderung anstößt, kriegt deshalb ein SSE Echo, weil die Seite neu geladen wird.
Hab aber auch schon in document.ready und Pageshow getestet. Keine Änderung.
Genauso wenn der Listener direkt im HTML-Code entweder direkt nach <body>, oder direkt vor </body> steht. Keine Änderung.

Wo muss ich den Listener einbinden, damit alle Clients den SSE erhalten, ohne neu zu laden?
 
Ich geh davon aus, das Problem ist der Zeitpunkt, wann der Event-Listener seine function ausführt.
der zeitpunkt ist wichtig, soweit stimmt das schon mal
solange du den eventlistener registrierst(bzw. das serverscript muss laufen), bevor die änderung erfolgt ist, passt das aber.
ich würde $(document).ready() nehmen

Im Moment in Pagebefore.
pagebeforeshow finde ich nur in der jQuery mobile docu, nutzt du die?
aber selbst da steht:
Note: The triggering of this event is deprecated as of jQuery Mobile 1.4.0. It will no longer be triggered in 1.6.0.

- - - Aktualisiert - - -

Hab aber auch schon in document.ready und Pageshow getestet. Keine Änderung.
das sollte allerdings gehen.

prinzipiell kannst du ja aber testen, ob es am server-script liegt oder am client-script, indem du im serverscript testweise jede sekunde etwas sendest und im clientscript dann eine ausgabe machst.
 
Ja before verwende ich.
Hab allerdings ne etwas ältere JQuery (+mobile)-Version<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>


Also, hab jetzt mal if ($neuezeit>$altezeit) rausgenommen. Dann kann ich mich vor alerts kaum retten. :)
funktioniert also , und zwar auf allen Clients.

Hab jetzt mal zum Verständnis in alle Page-Events ein Alert eingebaut, um die Reihenfolge zu sehen:
Pageready
Pagecreate
ProcessSSE **) meine Funktion um SSE´s abzufangen
Pagebeforeshow

Was auffällt ist, dass nach Create ein SSE gesendet wird. Kann es sein, dass beim Registrieren des Listeners die php neu gestartet wird? Das würde ein Senden erklären, da vor der Endlosschleife die Zeit auf einen alten Wert gesetzt wird.
Das würde auch erklären, warum nur der "auslösende" Client ne Nachricht kriegt, weil der grade den Listener registriert und ne Message startet.

Meine Vermutung: Der filemtime-Vergleich funktioniert nicht
 
Also, hab jetzt mal if ($neuezeit>$altezeit) rausgenommen. Dann kann ich mich vor alerts kaum retten. :)
funktioniert also , und zwar auf allen Clients.
geht also auf schon mal prinzipiell

Was auffällt ist, dass nach Create ein SSE gesendet wird. Kann es sein, dass beim Registrieren des Listeners die php neu gestartet wird?
nicht neu, sondern überhaupt erstmal, beenden musst du das php-script schon selbst, wenn dein client beendet wird

Meine Vermutung: Der filemtime-Vergleich funktioniert nicht
ja, $neuezeit wird als lokale variable im if (file_exists($filename)) gesetzt und im scope darüber abgefragt

- - - Aktualisiert - - -

allerdings hätte dann nie ein client eine msg bekommen
 
Also, ich habe mal das php script geändert.
Den Zeitvergleich rausgenommen, und alle 8 sek echo 'data: ' . $altezeit . ' ' . $neuezeit . "\n\n"; gesendet.

Wenn ich in der zwischenzeit eine Dateiänderung vornehme, wird trotzdem die Zeit nicht geändert.
Ergebnis: 1509028045 1509028045

Ist filemtime vielleicht doch nicht richtig?

Ich verändere die Datei mit folgendem Code:
PHP:
<?php  
if(isset($_POST)) 
{
   $message = $_POST['message'];   
   $file = $_POST['file'];
   header("Refresh:0");   
   $Obj=json_decode($message); 
   var_dump($message);
   $user=$Obj->user;  
   $Gegner=$Obj->Gegner;
   $Wert=$Obj->Wert;
   $ausgezahlt=$Obj->ausgezahlt; 
   $h=fopen($file,'r+');
   if (flock($h, LOCK_EX))   
   {  	    
   	  $Daten=json_decode(file_get_contents($file));	 	  
	  $Daten->$user->$Gegner->Wert=$Wert;
	  $Daten->$user->$Gegner->ausgezahlt=$ausgezahlt;
	  $Daten->$user->istBenutzer=true;	 
	  fseek($h, 0);
	  ftruncate($h, 0);
	  fwrite($h,json_encode($Daten));   
	  flock($h, LOCK_UN);
   }  
   fclose($h);
}
?>

- - - Aktualisiert - - -

Also wenn ich in Dreamweaver die Dateien auf dem Server beobachte, wird definitiv bei jeder Änderung eine neue Zeit dargestellt. Also wird die Datei definitiv geändert.

filemtime liefert mir aber immer die gleiche Zeit. Im php-manual steht, dass filemtime gecached ist. Liegt das vielleicht daran?
Einfach nur clearstatcache(); vor $neuezeit=filemtime($filename); bringt keine Änderung. Oder mache ich das mit dem Clearstatcache falsch?

PHP:
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
$altezeit=1508857791;
while (1) 
{     
   $filename = 'Daten.json';
   clearstatcache();
   $neuezeit=filemtime($filename);   
	  
   $h = fopen('Daten.json', 'r+');
   if (flock($h, LOCK_EX)) 
   { 	  
	
	 echo 'data: ' . date("d.m.Y - H:m",$neuezeit) . "\n\n";
		 
		
	 @ob_end_flush();
	 @flush();
	 $altezeit=$neuezeit;
		 	 
    }	
    flock($h, LOCK_UN);  
    fclose($h);
   
     sleep(8);
}
?>

- - - Aktualisiert - - -

OK, habs hingekriegt. Der Cache wars.

PHP:
 <?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
$altezeit=1508857791;
while (1) 
{     
   $filename = 'Daten.json';
   clearstatcache($filename);
   $neuezeit=filemtime($filename);   
      
   $h = fopen('Daten.json', 'r+');
   if (flock($h, LOCK_EX)) 
   {       
    
     echo 'data: ' . date("d.m.Y - H:m",$neuezeit) . "\n\n";
         
        
     @ob_end_flush();
     @flush();
     $altezeit=$neuezeit;
              
    }    
    flock($h, LOCK_UN);  
    fclose($h);
   
     sleep(8);
}
?>
 
Funktioniert leider nicht immer.
Das SSE sendet normalerweise ein Object mit einem Array aus Objects (normalerweise sollte in dem Array nur 1 Object sein. Nur wenn zeitgleich mehrere Änderungen gemacht werden, könnten mehrere Objekte im Array sein).

Aber oft kommt ein leeres Array zurück. Das muss irgendwie an den Serverseitigen PHP#s liegen.

Mal zum Ablauf:

Ich sende mit
HTML:
$.ajax(         /*Änderung hochladen*/
   {
	  type: "POST",
	  url: 'update.php',
	  data: {message :JSON.stringify({"user":user,"Gegner":Gegner,"Wert":werte,"ausgezahlt":ausgezahlt}), file: 'Daten.json'},  
	  success: function(data)
	  {
		 $.mobile.changePage($("#home"), { transition: "pop"});
	  },		   
	  error:function()
	  {
		  
	  }
   });
folgende Daten:
Code:
{"user":"Hubi","Gegner":"Muba","Wert":["-4,80","-3,60","-2,40","-1,20","0,00","-0,40","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00"],"ausgezahlt":false}"

Den Ablauf in der "update.php" erläutere ich mit Kommentaren im Code:
PHP:
<?php  
if(isset($_POST)) 
{
   $message = $_POST['message'];   //Die Daten
   $file = $_POST['file'];
   header("Refresh:0");   
   $Obj=json_decode($message);  //Daten in Objekt wandeln
   var_dump($message);   //Hiermit prüfe ich, ob die Message ankommt 
   $user=$Obj->user;     // Die einzelnen Objektproperties in Variablen speichern
   $Gegner=$Obj->Gegner;
   $Wert=$Obj->Wert;
   $ausgezahlt=$Obj->ausgezahlt; 
   
   $handle=fopen("change.json",'r+');   //Change-Datei öffnen - Hier werden die hochgeladenen Änderungen gespeichert
   if (flock($handle, LOCK_EX))   
   {  	    
  	  $Daten=json_decode(file_get_contents("change.json"));	//Vorhandenes "change"-Object auslesen (normalerweise leeres Array)
	  var_dump(json_encode($Daten)) ;   
	  $Array = $Daten->change;  //Das Array aus dem Object ziehen
	  $object = new stdClass();  //Ein Object erstellen, um die hochgeladenen Änderungen einzupflegen
	  $object->user=$user;
	  $object->Gegner=$Gegner;
	  $object->Wert=$Wert[0];
	  $object->alterWert=$Wert[1];	  
	  array_push($Array,$object);   // Das neue Object als Array-Item einhängen
	  $Daten->change=$Array;      // Und wieder ins Objekt "change" einhängen
     var_dump(json_encode($Daten)) ;  //Überprüfen, welche Daten hochgesendet werden 
	  fseek($handle, 0);
	  ftruncate($handle, 0);   //  --------Bis hierhin ist alles OK. Die Daten die geschrieben werden sollen sind immer vorhanden.
	  fwrite($handle,json_encode($Daten));   // Und in die Datei schreiben.
	  flock($handle, LOCK_UN);
   }  
   fclose($h);
   
   $h=fopen($file,'r+');              // Hier unten werden die Daten nochmal in eine "Gesamt-Datei" eingepflegt. Hat jetzt mit dem Problem nix zu tun
   if (flock($h, LOCK_EX))   
   {  	    
   	  $Daten=json_decode(file_get_contents($file));	 	  
	  $Daten->$user->$Gegner->Wert=$Wert;
	  $Daten->$user->$Gegner->ausgezahlt=$ausgezahlt;
	  $Daten->$user->istBenutzer=true;
	 
	  fseek($h, 0);
	  ftruncate($h, 0);
	  fwrite($h,json_encode($Daten));   
	  flock($h, LOCK_UN);
   }  
   fclose($h);
}
?>

Da sich nun das Datum der "Change.json" geändert hat, werden die Änderungen per SSE gesendet:

PHP:
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
$altezeit=1508857791;   //Beim start eine Zeit kleiner als Dateizeit setzen
while (1)                     
{     
   $filename = 'change.json';
   clearstatcache($filename);
   $neuezeit=filemtime($filename);   //Dateizeit holen
   if ($neuezeit>$altezeit)   // vergleichen, ob eine Datei-Änderung gemacht wurde
   {	  
	  $h = fopen($filename, 'r+');
	  if (flock($h, LOCK_EX)) 
	  { 	  	 
		 $jsondata=file_get_contents($filename);		 //Inhalt von "change.json" auslesen	***Da hier nur gesendet wird, wenn änderungen ins File geschrieben wurden, 
                                                                                            // dürfte das Array nie leer sein!!!  Ist es aber öfter!!!  Es kommt {"change":[]} zurück   *****		    
		 echo "data: $jsondata\n\n";	                        //Inhalt senden
		 @ob_end_flush();
		 @flush();		
                 $obj=json_decode($jsondata);	 //Inhalt in Objekt wandeln
		 $obj->change = array();		//Array leeren, da ja die Änderungen gesendet wurden	   
		 fseek($h, 0);
		 ftruncate($h, 0);
		 fwrite($h,json_encode($obj));    // Object "change" mit leerem Array in Datei schreiben
		 clearstatcache($filename);
		 $altezeit=filemtime($filename); 	// alte Zeit auf neue Dateizeit setzen	 
	  }	
	  flock($h, LOCK_UN);  
	  fclose($h);
   }
   sleep(1);
}
?>

Woran könnte das liegen?
 
Zuletzt bearbeitet von einem Moderator:
Woran könnte das liegen?
das hatten wir doch schon
das mit dem change wird nicht funktionieren, da ja n personen die änderungen mitbekommen müssen. du findest nicht den zeitpunkt um das change zurückzusetzen.


PHP:
		 $obj->change = array();		//Array leeren, da ja die Änderungen gesendet wurden	   
		 fseek($h, 0);
		 ftruncate($h, 0);
		 fwrite($h,json_encode($obj));    // Object "change" mit leerem Array in Datei schreiben

wenn du change zurücksetzt, nachdem die daten an den 1. user gesendet wurden, bekommen alle anderen nichts mehr
 
wenn du change zurücksetzt, nachdem die daten an den 1. user gesendet wurden, bekommen alle anderen nichts mehr
Versteh ich jetzt nicht. Ich dachte, das SSE wird einmal gesendet, und alle Clients mit einem Eventlistener empfangen es gleichzeitig. Wie beim Fernseher. Einmal gesendet, und wer die Frequenz eingestellt hat, empfängt.
Sonst würde das ja bedeuten, bei fiktiven 1 Mio Usern, muss das SSE 1 Mio mal gesendet werden. Oder hab ich hier grundsätzlich was nicht verstanden?

das mit dem change wird nicht funktionieren, da ja n personen die änderungen mitbekommen müssen. du findest nicht den zeitpunkt um das change zurückzusetzen.

Also es gibt insgesamt nur 25 User. Alle paar Minuten geben 4 Leute Daten ein. Selbst wenn alle gleichzeitig absenden, kommen höchstens 4 Änderungen. Deshalb ein Array. Und das gesamte Array wird wieder runtergesendet.

Ich wollte halt vermeiden, dass jedesmal das ganze Datenpaket gesendet wird. Es werden ja nur die Änderungen gebraucht.
 
Versteh ich jetzt nicht. Ich dachte, das SSE wird einmal gesendet, und alle Clients mit einem Eventlistener empfangen es gleichzeitig. Wie beim Fernseher. Einmal gesendet, und wer die Frequenz eingestellt hat, empfängt.
nee, tcp und damit http ist verbindungsorientiert, client und server bauen eine verbindung auf. wenn du etwas sendest, musst du es für jede verbindung machen.

Sonst würde das ja bedeuten, bei fiktiven 1 Mio Usern, muss das SSE 1 Mio mal gesendet werden. Oder hab ich hier grundsätzlich was nicht verstanden?
bei 1 mio usern laufen in deinem fall 1 mio scripte die jeweils 1 mal senden - sonst wäre die ganze locking-geschichte ja nicht notwendig gewesen

Also es gibt insgesamt nur 25 User. Alle paar Minuten geben 4 Leute Daten ein. Selbst wenn alle gleichzeitig absenden, kommen höchstens 4 Änderungen. Deshalb ein Array. Und das gesamte Array wird wieder runtergesendet.
ja, das sagst du immer wieder, aber auch bei 25 usern kann man sich eine datenstruktur ausdenken, die optimal ist

Ich wollte halt vermeiden, dass jedesmal das ganze Datenpaket gesendet wird. Es werden ja nur die Änderungen gebraucht.
wenn du für jeden nutzer einen index vergibst und dann eine matrix [user][user] aufbaust und darin ein array von objekten der art {amount: 1.50, verified: 1, timestamp: <<servertime>> } speicherst kannst mit data[udo_idx] alle einträge finden die für udo sind.
dann kannst du data[udo_idx][peter_idx] alle einträge finden die für udo von peter sind, da du nicht weißt, wer alles einträge gemacht hat, musst du für udo alle einträge aller user abfragendata[udo_idx][0-n]. drin sind dann wieder n einträge, entweder schon aufsummiert oder auch nicht für bestätigte beträge, noch nicht bestätigte und abgelehnte. die sind jeweils mit zeitstempel, so dass du nur die senden müsstest, welche nach der letzten abfrage hinzugekommen sind.
 
Hmm, jetzt steig ich geistig langsam aus. Versteh nicht genau wie du das meinst.
Meine "Daten.json" ist eigentlich schon als Matrix aufgebaut. Vielleicht kann man da ansetzen.

Momentan sieht die Datei (verkürzt) so aus:
Code:
{
[INDENT]"Udo":
{
[INDENT]"Peter":{"Wert":["-1,60","-3,20","-2,80","-2,40","-2,00","-1,20","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00"],"ausgezahlt":false},
"Franz":{"Wert":["0,00","-0,40","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00"],"ausgezahlt":false},[/INDENT]
},"istBenutzer":true},

"Peter":
{
[INDENT]"Udo":{"Wert":["1,60","3,20","2,80","2,40","2,00","1,20","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00"],"ausgezahlt":false},
"Franz":{"Wert":["0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00"],"ausgezahlt":false},[/INDENT]
},"istBenutzer":true},

"Franz":
{
[INDENT]"Udo":{"Wert":["0,00","0,40","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00"],"ausgezahlt":false},
"Peter":{"Wert":["0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00"],"ausgezahlt":false},[/INDENT]
},"istBenutzer":false}[/INDENT]
}

Ziel ist jetzt, wenn Udo bei Peter einen Eintrag macht (Die Werte im Array werden nach rechts verschoben, der letzte fällt raus):
Code:
{
[INDENT]"Udo":
{
[INDENT]"Peter":{"Wert"["555,55","-1,60","-3,20","-2,80","-2,40","-2,00","-1,20","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00"],"ausgezahlt":false},
"Franz":{"Wert":["0,00","-0,40","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00","0,00"],"ausgezahlt":false},[/INDENT]
},"istBenutzer":true},
.........
...........
[/INDENT]
}

soll Peter Quasi Peter--Udo--555,55---1,60 gesendet kriegen.
Auf der Client-Seite wird dann bei Udo und Peter die Zelle gelb dargestellt, weil Peter noch den alten Wert von Udo drin hat.
Sind beide Werte identisch -> grün
völlig falsch-> rot.
Clientseitig hab ich den vergleich schon. Nur ums senden gehts.

Kanns du vielleich anhand dieses Beispiel erklären, wie du das meinst?
 
du speicherst das so etwa
Code:
{
  user:
  {
    udo: {
      idx: 0,
      timestamp: <<servertime>>
    },
    peter: {
      idx: 1,
      timestamp: <<servertime>>
    },
    franz: {
      idx: 2,
      timestamp: <<servertime>>
    }
  },
  data: [
    [
      [],
      [
        {
          amount: 1.50, 
          verified: 1, 
          timestamp: <<servertime>>
        }, 
        {
          amount: 2.50, 
          verified: 1, 
          timestamp: <<servertime>> 
        },
        {
          amount: 3.50, 
          verified: 0, 
          timestamp: <<servertime>> 
        }
      ],
      [
        {
          amount: 0.50, 
          verified: 1, 
          timestamp: <<servertime>>
        }, 
        {
          amount: 0.50, 
          verified: 1, 
          timestamp: <<servertime>> 
        }, 
        {
          amount: 0.50, 
          verified: 1, 
          timestamp: <<servertime>> 
        }
      ]
    ],
    [
      [
        {
          amount: -1.50, 
          verified: 1, 
          timestamp: <<servertime>>
        }, 
        {
          amount: -2.50, 
          verified: 1, 
          timestamp: <<servertime>> 
        },
        {
          amount: -3.50, 
          verified: -1, 
          timestamp: 99 
        }
      ],
      [],
      [
        {
          amount: 0.25, 
          verified: 1, 
          timestamp: <<servertime>>
        }, 
        {
          amount: 0.50, 
          verified: 1, 
          timestamp: <<servertime>> 
        }, 
        {
          amount: 0.75, 
          verified: 1, 
          timestamp: <<servertime>> 
        }
      ]
    ],
    [
      [
        {
          amount: -0.50, 
          verified: 1, 
          timestamp: <<servertime>>
        }, 
        {
          amount: -0.50, 
          verified: 1, 
          timestamp: <<servertime>> 
        }, 
        {
          amount: -0.50, 
          verified: 1, 
          timestamp: <<servertime>> 
        }
      ],
      [
        {
          amount: -0.25, 
          verified: 1, 
          timestamp: <<servertime>>
        }, 
        {
          amount: -0.50, 
          verified: 1, 
          timestamp: <<servertime>> 
        }, 
        {
          amount: -0.75, 
          verified: 1, 
          timestamp: <<servertime>> 
        }
      ],
      []
    ]
  ]
}

init.php
aufruf durch udo:
alle einträge aus data[user.udo.idx] werden gesendet
aufruf durch peter:
alle einträge aus data[user.peter.idx] werden gesendet

update.php
udo hat gegen peter gespielt
udo kommt online und trägt seinen betrag im array data[user.udo.idx][user.peter.idx][] und data[user.peter.idx][user.udo.idx][] ein
bei data[user.udo.idx][user.peter.idx][] mit verified: 0 und bei data[user.peter.idx][user.udo.idx][] mit verified: -1

sse.php
aufruf durch udo:
udo werden alle einträge aus data[user.udo.idx][0-n][] gesendet deren timestamp größer als user.udo.timestamp ist
damit bekommt er den eintrag den er gerade gemacht hat, und sieht am verified: 0, dass er diesen bestätigt hat, peter aber noch nicht
user.udo.timestamp wird auf die aktuelle serverzeit gesetzt
aufruf durch peter:
peter werden alle einträge aus data[user.peter.idx][0-n][] gesendet deren timestamp größer als user.peter.timestamp ist
damit bekommt er den eintrag den udo gemacht hat, und sieht am verified: -1, dass er diesen bestätigen muss
user.peter.timestamp wird auf die aktuelle serverzeit gesetzt

confirm.php
peter bestätigt den eintrag von udo
data[user.peter.idx][user.udo.idx][2] und data[user.udo.idx][user.peter.idx][2] wird auf verified: 1 gesetzt, und der timestamp wird aktualisiert


aus dem sse.php bekommen jetzt peter und udo diesen eintrag (weil der zeitstempel größer als der beim jeweiligen user..... ist) und sehen am verified: 1, dass er von beiden bestätigt wurde und können ihn entsprechend kennzeichnen

jetzt musst du nur noch etwas machen für den fall, dass peter und udo gleichzeitig update.php aufrufen, damit der eintrag nicht doppelt bei beiden eingetragen wird
 
Zuletzt bearbeitet:
sse.php
aufruf durch udo:

udo werden alle einträge aus data[user.udo.idx][0-n][] gesendet

Versteh ich immer noch nicht: Das SSE wird doch nicht von bestimmten Personen aufgerufen. Es hängen doch alle mit dem Eventhandler dran und kriegen alle die SSE.

Die sse.php weiß weder, wer sie grade aufruft, noch wer grade empfängt. Oder lieg ich hier wieder falsch?

Aber ich hätte noch ne andere Idee, mit der ich wenig ändern müsste. Was hältst du davon:

Udo zahlt an Peter. Eintrag in change.php: change-Index:0---Udo--Peter--555,55---1,60--verified:false
Gleichzeitig Franz zahlt an Fritz. Eintrag in change.php: change-Index:1---Franz--Fritz--111,11---3,20--verified:false

Wenn Change-Array nicht leer-> sende SSE

Alle Empfangen. Wenn Peter empfängt If user==Data[Gegner].... sendet er zurück change-Index:0---Varified:true

In der update.php: Wenn verified:false kommt, eintragen in Change.json, wenn change-Index:0---verified:true kommt löschen aus change.json, da der richtige User empfangen hat.
Der change-Index wird pro Eintrag immer um 1 erhöht bis 9, dann wieder bei 0 anfangen, da wohl nie mehr als 10 Einträge vorkommen.
Es wird nahezu nie vorkommen, dass jemand Einträge für einen Offline-User macht.

Müsste doch eigentlich funktionieren!?

- - - Aktualisiert - - -

Bzw, man könnte immer den letzten Index um 1 erhöhen. Wenn keiner vorhanden, Index=0. Dann dürfen es auch mehr als 10 Einträge sein.
 
Das SSE wird doch nicht von bestimmten Personen aufgerufen. Es hängen doch alle mit dem Eventhandler dran und kriegen alle die SSE.
du hast für jeden user(bzw. für jede offene verbindung) ein sse laufen.

Die sse.php weiß weder, wer sie grade aufruft, noch wer grade empfängt. Oder lieg ich hier wieder falsch?
dass muss das sse doch aber wissen, weil es nur die informationen des jeweiligen users senden soll, alternativ müsstest du sonst immer alles senden und die clients suchen sich das ihre raus, das ist aber nicht optimal

Aber ich hätte noch ne andere Idee, mit der ich wenig ändern müsste. Was hältst du davon:
sollte gehen
 
Hab immer noch Probleme mit meiner "Update.php".

Das Programm funktioniert oft problemlos.
Bin am Testen mit 2 Clients am Desktop. Ein User auf Firefox, ein User auf Safari.
Ich teste ca 20 mal (gefühlt. mal mehr, mal weniger). Einer zahlt, beide werden gelb dargestellt. Der Gegner kassiert, alles grün. Scheinbar funktioniert alles Problemlos.
Irgendwann hörts auf, die Farben passen nicht mehr.

normalerweise steht in der "Change.json": {"change":[]}
change ist ein leeres Array.
zahlt/kassiert jemand, werden die daten hochgeschickt und als Objekt in das array eingefügt (Hier stehn jetzt 2 Objekte drin):
{"change":[{"index":0,"user":"Flauschi","Gegner":"Hubi","Wert":"34,00","alterWert":"33,20"},{"index":1,"user":"Flauschi","Gegner":"Hubi","Wert":"34,80","alterWert":"34,00"}]}

Der Client schickt die per SSE empfangenen Daten (identifizierbar durch den Index) wieder hoch mit "verified". Dann wird das Array-Indizes mit dem passenden Index gelöscht.

Funktioniert wunderbar. Doch nach etlichen Versuchen, steht in der "Change.json":
{"change":{{"index":0,"user":"Flauschi","Gegner":"Hubi","Wert":"34,00","alterWert":"33,20"},{"index":1,"user":"Flauschi","Gegner":"Hubi","Wert":"34,80","alterWert":"34,00"}}}

Man beachte die Klammern!! Aus [ wird {

Plötzlich wird aus dem Array ein Objekt!. Dann funktioniert natürlich die verarbeitung des Arrays nicht mehr. Ich hab jetzt so oft Probiert, ich finde einfach keine regel, wann das passiert.
Mal klappts 5X, mal 20X.

Die Daten werden hochgesendet mit
Code:
$.ajax(         /*Änderung hochladen*/
   {
	  type: "POST",
	  url: 'update.php',
	  data: {message :JSON.stringify({"index":-1,"user":user,"Gegner":Gegner,"Wert":werte,"ausgezahlt":ausgezahlt,"verified":false,"Auszahlung":false}), file: 'Daten.json'},  
	  success: function(data)
	  {
		 $.mobile.changePage($("#home"), { transition: "pop"});
	  },		   
	  error:function()
	  {
		  
	  }
   });

Index -1 wenn nicht verified (also keine Bestätigung vom SSE, sondern zahlen/kassiern. Der korrekte Index wird nur bei "verified" mitgesendet)

Die update.php:
PHP:
<?php  
if(isset($_POST)) 
{
   $message = $_POST['message'];   
   $file = $_POST['file'];
   header("Refresh:0");   
   $Obj=json_decode($message); 
   $index=$Obj->index;
   $user=$Obj->user;  
   $Gegner=$Obj->Gegner;
   $Wert=$Obj->Wert;
   $ausgezahlt=$Obj->ausgezahlt; 
   $verified=$Obj->verified;
   $Auszahlung=$Obj->Auszahlung;
   
   if($Auszahlung==false)
   {
	  $handle=fopen("change.json",'r+');
	  if (flock($handle, LOCK_EX))   
	  {  	    
		 $Daten=json_decode(file_get_contents("change.json"));	//Change-Daten lesen
		 $Array = $Daten->change; //Das Array aus dem Objekt "change" filtern
		
		 if($verified==true)  //Durch SSE verifizierte Daten. Interessiert hier nicht
		 {
		   if($index>=0)
		   { 
			  for($i=0;$i<sizeof($Array);$i++)
			  {  
				 if ($Array[$i]->index==$index)
				 {
					unset($Array[$i]);
				 }
			  }
		   }		   
		 }
		 else
		 {			
			if(sizeof($Array)==0) //wenn Array leer (normalzustand)
			{
			  $index=0;  //Index für das zu schreibende Array-Indizes festlegen
			}
			else
			{	
			  $lastArrayObject=new stdClass();
			  $lastArrayObject=$Array[sizeof($Array)-1];
			  $index=$lastArrayObject->index+1;   //letztbekannter Index +1 
			}
			$object = new stdClass(); //Daten einem neuen Objekt zuweisen
			$object->index=$index;
			$object->user=$user;
			$object->Gegner=$Gegner;
			$object->Wert=$Wert[0];
			$object->alterWert=$Wert[1];  
			array_push($Array,$object);  //Objekt in das Array einreihen
			
		 }
		
		 $Daten->change=$Array;  //Das Array ins Objekt "change" schreiben
		
		 fseek($handle, 0);   //und in die Datei schreiben
		 ftruncate($handle, 0);
		 fwrite($handle,json_encode($Daten));   
		 flock($handle, LOCK_UN);
	  }  
	  fclose($h);
   }
   
   if($verified==false)  //Ab hier werden die Daten in die "Daten.json" geschrieben und hat mit dem Problem nix zu tun
   {
	  $h=fopen($file,'r+');
		
	  if($Auszahlung==false)
	  {
		  if (flock($h, LOCK_EX))   
		 {  	    
			$Data=json_decode(file_get_contents($file));	 	  
			$Data->$user->$Gegner->Wert=$Wert;
			//var_dump($Data->$user->$Gegner->Wert);
			$Data->$user->$Gegner->ausgezahlt=$ausgezahlt;
			$Data->$user->istBenutzer=true;
		   
			fseek($h, 0);
			ftruncate($h, 0);
			fwrite($h,json_encode($Data));   
			flock($h, LOCK_UN);
		 } 
		 
	  }
	  else
	  {
		 if (flock($h, LOCK_EX))   
		 {  	    
			$Data=json_decode(file_get_contents($file));	 	  
			$Data->$user->$Gegner->Auszahlwert=$Wert;
			$Data->$user->$Gegner->ausgezahlt=$ausgezahlt;
			
			fseek($h, 0);
			ftruncate($h, 0);
			fwrite($h,json_encode($Data));   
			flock($h, LOCK_UN);
		 } 
		 
	  }
	  fclose($h);
   }
}
?>

wie kommt es dazu, dass statt einem Array ein Objekt geschrieben wird?
 
nee, hab nix unterschlagen.

Was ist ungültig? Mein JSON, oder nachdem die Klammer falsch gesetzt ist?

- - - Aktualisiert - - -

Doch ich hab was unterschlagen:


Aus
{"change":[{"index":1,"user":"Flauschi","Gegner":"Hubi","Wert":"33,20","alterWert":"34,00"},{"index":2,"user":"Flauschi","Gegner":"Hubi","Wert":"32,40","alterWert":"33,20"}]}

wird

{"change":{"1":{"index":1,"user":"Flauschi","Gegner":"Hubi","Wert":"33,20","alterWert":"34,00"},"2":{"index":2,"user":"Flauschi","Gegner":"Hubi","Wert":"32,40","alterWert":"33,20"}}}

- - - Aktualisiert - - -

Kann das mit dem unset zu tun haben? Wenn ich richtig gelesen hab, wird durch unset gelöscht, ohne den index nachzuführen.
D.h. wenn ich Array[2] lösche, und später durch ne Zählschleife auf den index 2 zugreife, dürfte es Probleme geben.

Hab jetzt
unset($Array[$i]);
durch array_splice($Array,$i,1); ersetzt.

Das erklärt aber nicht, warum aus dem Array ein Objekt wird....
 
Zurück
Oben