| Autor |
Beitrag |
Boldar
      
Beiträge: 1555
Erhaltene Danke: 70
Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
|
Verfasst: Do 24.06.10 19:12
Hallo,
ich möchte gerne ein Spiel auf meine Webseite streamen.
D.h. ich möchte aus dem Browser heraus das Bild sehen und das Spiel steuern. Das Spiel soll dann als extra Anwendung auf dem Server laufen. (Ist nen älteres Spiel und sehr anspruchslos, Reaktionszeiten sind auch nicht so wichtig, also sollte insofern eigentlich gehen.)
Ich habe mich mal informiert, und denke, das man das vielleicht mit ajax machen könnte.
Clientseitig ist mir auch ungefähr vom Konzept her klar, wie ich das machen könnte, also mit javascript die Frames anzeigen, in onmousemove die Daten übertragen usw. Bloss:
Wie komme ich Serverseitig die Kommunikation zwischen Spiel und php hin?
Wie macht man sowas generell?
Also wie kommt man aus php generell an Daten ran?
Ich könnte natürlich ein "externes" progg schreiben, was die Daten vom Spiel irgendwie an die Server-applikation überreicht. Aber wie kriege ich eben diese Kommunikation mit dem Server hin?
So ganz schlecht sollten die Reaktionszeiten natürlich auch nicht sein.
mfg Boldar
Edit: Mir ist grade eingefallen, was ich fürn Müll geschrieben habe...
|
|
Sinspin
      
Beiträge: 1338
Erhaltene Danke: 120
Win 10
RIO, CE, Lazarus
|
Verfasst: Do 24.06.10 21:22
Ich habe sowas noch nicht gemacht und in deinem Fall verstehe ich auch den Sinn nicht ganz. Aber mal angenommen du machst das einfach um was zu lernen:
1. Servertechnologie wahlweise:
A : Webserver mit PHP. Verzeichnis über das die Daten ausgetauscht werden und ein Programm das die Informationen zusammenstellt und Aktionen ausführt.
B : Ein Delphi Programm was via Indy oä. einen HTTP Server miemt. Das verwaltet dann die Informationen und Aktionen.
2. Rauswärts ist ja nur das Bild nötig. Das kannst du dir mit einem einfachen "abfotografieren" des Spielefensters hohlen und stellst es zum abrufen bereit.
3. Reinwärts musst du ja zumindest Mausaktionen oder auch Tasteneingaben via Posts, nach Möglichkeit in Echtzeit senden. Dafür macht sich Javascript / Ajax sicher ganz gut. Das Ding ist ja aber das du andauernd das Bild aktualisieren musst, auf die Mausbewegung achten musst und auch Tastendrücke sind sicher nötig.
Ich glaube, ich würde da eher auf ein Java Applet setzen. Da könntest du dann sogar den HTTP Port auf deinem Server für ein eigenes Protokoll misbrauchen, solange du dort drauf nicht schon einen HTTP Server laufen hast (dann geht auch die variante mit der eigenen Anwedung nicht).
Natürlich kann man mit einem Applet auch einen normalen Webserver bedienen.
Wieso ist das hier eigentlich OT?
_________________ Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?
|
|
Hidden
      
Beiträge: 2242
Erhaltene Danke: 55
Win10
VS Code, Delphi 2010 Prof.
|
Verfasst: Do 24.06.10 21:26
Hi
Als proof-of-concept sicherlich nicht uninteressant - aber ist es bei einer instabilen/laggenden Verbindung nicht doch wirklich besser, alle nicht-interaktiven Bestandteile zuerst herunterzuladen, und dann lokal auszuführen?
lg,
_________________ Centaur spears can block many spells, but no one tries to block if they see that the spell is a certain shade of green. For this purpose it is useful to know some green stunning hexes. (HPMoR)
|
|
Boldar 
      
Beiträge: 1555
Erhaltene Danke: 70
Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
|
Verfasst: Do 24.06.10 21:43
Über Sinn und Uninn braucht man wohl eh nicht reden...
Ich will das ja nur so Just4fun machen.
Also, ich habe mir nun folgendes Überlegt:
Ich schmeisse das HTdocs Verzeichnis des Webservers (xampp) auf eine Ramdisc, des Speeds wegen.
Dann speichere ich mit Delphi die Screenshots in einem Unterordner.
Clientseitig greife ich dann mit javascript darauf zu.
Auf java wollte ich Verzichten, damit das auch auf Systemen läuft, wo java nicht zur verfügung steht.
Bloss: wie verhindere ich, das der Screenshot gerade geschrieben wird, während er angefordert wird? Ich müsste dass also Serverseitig irgendwie buffern.
Und wie schicke ich am besten die Mausbewegungen und so zurück?
|
|
Hidden
      
Beiträge: 2242
Erhaltene Danke: 55
Win10
VS Code, Delphi 2010 Prof.
|
Verfasst: Do 24.06.10 21:53
Hi
Okay, dann ist gut.  War auch nur für's Protokoll, für die Kleinen - zu Hause nicht so nachmachen
Läuft das ganze in einer Anwendung? Ein Flag in Form einer Semaphor-Variablen macht das ganze Threadsafe.
Bei zwei Anwendungen weiß ich nicht: Die Semaphor-Var in eine Datei(die der Größe wegen sehr unwahrscheinlich gleichzeitig gelesen und geschrieben würde)?
lg,
_________________ Centaur spears can block many spells, but no one tries to block if they see that the spell is a certain shade of green. For this purpose it is useful to know some green stunning hexes. (HPMoR)
|
|
Boldar 
      
Beiträge: 1555
Erhaltene Danke: 70
Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
|
Verfasst: Do 24.06.10 21:58
naja, der Apache-Webserver schickt die Dateien ja zum Client.
Wär auch nicht schlimm, wenn hin und wieder mal ein Frame verloren geht. Vielleicht reicht der Speed der Ramdisc ja auch, ich probier das mal aus...
|
|
Sinspin
      
Beiträge: 1338
Erhaltene Danke: 120
Win 10
RIO, CE, Lazarus
|
Verfasst: Do 24.06.10 22:18
Zur Synchronisation von verschiedenen Anwendungen machen sich meiner Erfahrung nach Dateien immernoch am besten. Dabei geht es nicht darum irgend ein Flag in einer Datei zu setzen, das kann auch schon wieder zu lange dauern.
Rein mit dem Namen der Datei (Semaphore Datei) also mit dessen Anwesenheit geht das besser.
Also,
der Schreibende legt eine Datei "schreiberling.xxx" an.
Der Lesende schaut erst nach ob es die Datei gibt, erstellt dann seinerseits eine Datei "leseratte.xxx" wenn er keine findet.
Der Lesende schaut nun nochmal ob die Datei vom schreibenden nicht doch noch aufgetaucht ist. Wenn ja löscht er seine Datei wartet ein bisschen und fängt mit der Arbeit von vorne an. Wenn nicht, liest er das Bild und löscht dann seine Datei.
Der Schreibende geht eigentlich genauso vor. Bevor er seine Datei erstellt schaut er ob die vom Lesenden da ist und schaut danach nochmal nach. Ist keine da schreibt er ansonsten fängt er mit dem ganzen Spass halt nochmal ein bisschen später an.
Du kannst es aber auch ganz ohne Semaphores machen indem du einfach die Datei in jedem Programm zum schreiben öffnest. Dann sollte es bei dem, der später dran ist, knallen, der probiert es dann halt später nochmal.
_________________ Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?
Für diesen Beitrag haben gedankt: Hidden
|
|
Boldar 
      
Beiträge: 1555
Erhaltene Danke: 70
Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
|
Verfasst: Do 24.06.10 22:38
Das Problem ist nur, dass ich den Apache-Server nicht umprogrammieren kann.
|
|
Boldar 
      
Beiträge: 1555
Erhaltene Danke: 70
Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
|
Verfasst: Sa 26.06.10 23:41
So, ich habe das von Sinspin mit der Synchronisation über Dateien jetzt umgesetzt.
Ich habe also eine Datei img.racces, die vom php-script erstellt wird und signalisiert, dass gelesen wird, sowie eine Datei img.wacces, die vom Delphi-prog geschrieben wird um zu signalisieren, dass geschrieben wird.
Bloss funktioniert es nicht.
Mein javascript sieht so aus:
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
| <html> <head> <title>Ajax</title> </head> <body onmousemove = "move()"> <script type="text/javascript" language="JavaScript"> newImage = new Image(); function LoadNewImage() { var unique = new Date(); document.images.stream.src = newImage.src; newImage.src = "img.php?time=" + unique.getTime(); } function InitialImage() { var unique = new Date(); newImage.onload = LoadNewImage; newImage.src = "img.php?time=" + unique.getTime(); document.images.stream.onload=""; } </script> <img src="img.php" name="stream" onload="InitialImage()" width="640" height="480"> </body> </html> |
Die img.php sieht so aus:
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| <?php test(); function test () { while (file_exists('img.wacces')) {} $datei = fopen('img.racces', w); fclose($datei); if (file_exists('img.wacces')) { unlink('img.racces'); test(); }; readfile ('img.png'); unlink('img.racces'); } ?> |
Und der Delphi-code so:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, tlhelp32, StdCtrls, ExtCtrls, pngunit;
type TForm1 = class(TForm) Timer1: TTimer; procedure Timer1Timer(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private public end;
var Form1: TForm1;
implementation
{$R *.dfm}
procedure MakeScreenShot(const ATarget: TBitmap); var DesktopDC: HDC; begin DesktopDC := CreateDC('DISPLAY', nil, nil, nil); try ATarget.PixelFormat := pfDevice; ATarget.Width := 1280; ATarget.Height := 1024; BitBlt(ATarget.Canvas.Handle, 0, 0, 1280, 1024, DesktopDC, 0, 0, SRCCOPY); finally DeleteDC(DesktopDC); end; end;
var bmp: TBitmap;
procedure TForm1.FormCreate(Sender: TObject); begin bmp:=TBitmap.Create; end;
procedure TForm1.FormDestroy(Sender: TObject); begin bmp.free; end;
procedure TForm1.Timer1Timer(Sender: TObject); var f: file; begin if not fileexists('I:\htdocs\ajax\img.racces') then begin Assignfile(f,'I:\htdocs\ajax\img.wacces'); Rewrite(f); closefile(f); if not fileexists('I:\htdocs\ajax\img.racces') then begin makescreenshot (Bmp); pngunit.WriteBitmapToPngFile('I:\htdocs\ajax\img.png', bmp, clfuchsia); end; deletefile ('I:\htdocs\ajax\img.wacces'); end; end;
end. |
Trotzdem kommen sich die Programme noch in die Quere.
|
|
Sinspin
      
Beiträge: 1338
Erhaltene Danke: 120
Win 10
RIO, CE, Lazarus
|
Verfasst: Mo 28.06.10 12:03
Du hast es ja auch nicht so gemacht wie ich es geschrieben habe.
Wesentlich ist das der Akteur erst seine Datei anlegt und dann testet ob die andere da ist. Ist sie da löscht er seine, wartet ein bisschen um es später nochmal zu probieren.
Zusätzlich vorneweg testen ist auch ok, so kann man sich das anlegen der eigenen sparen falls schon eine fremde da ist. Wichtig ist aber eben der Test auf das Vorhandensein der andreren _nachdem_ man seine eigene erstellt hat.
Das vorgehen das du im PHP Script verwendest musst du auch in Delphi umsetzen. Da fehlt die doppelte Prüfung.
Ansonsten, bist du dir sicher das PHP die Dateien im richtigen Verzeichnis erstellt werden? Es sollte dann aber eigentlich gehen. Ich verwende diese Methode um Programme im Netzwerk zu Synchronisieren.
_________________ Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?
|
|
Boldar 
      
Beiträge: 1555
Erhaltene Danke: 70
Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
|
Verfasst: Mo 28.06.10 16:08
|
|
Flamefire
      
Beiträge: 1207
Erhaltene Danke: 31
Win 10
Delphi 2009 Pro, C++ (Visual Studio)
|
Verfasst: Mo 28.06.10 16:20
Yeah! Damit hast du das, was man Wettlaufsituation nennt und damit ein potenzielles Deadlock, oder zumindest nicht das was du willst, da es möglich ist, dass einer immer schreibt und der andre nie liest.
Außerdem wird dir durch die rekursiven Aufrufe dein PHP-Server langsam aber sicher abschmieren.
Hier solltest du das Betriebssystem verwenden, um das zu synchronisieren (z.b. per Mutex, Semaphor etc)
|
|
Boldar 
      
Beiträge: 1555
Erhaltene Danke: 70
Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
|
Verfasst: Mo 28.06.10 19:43
Flamefire hat folgendes geschrieben : |
Hier solltest du das Betriebssystem verwenden, um das zu synchronisieren (z.b. per Mutex, Semaphor etc) |
Das würde aber vorraussetzen, den Server neu zu schreiben, was meine Fähigkeiten übersteigt.
Ich versuche jetzt erstmal einen Hook auf ntreadfile, der dann direkt das png zurückgibt.
|
|
Flamefire
      
Beiträge: 1207
Erhaltene Danke: 31
Win 10
Delphi 2009 Pro, C++ (Visual Studio)
|
Verfasst: Mo 28.06.10 21:47
dann 3 möglichkeiten:
1) php kann sowas.
2) du rufst mit php eine dll/programm auf, die das macht. (das geht)
3) Du beschäftigst dich mal mit dem Thema Verklemmungen und schreibst dann eine bessere Datei-Sperre.
Sowas wie:
eigene Datei schreiben
gucken ob andere Datei existiert
ja->eigene lsöchen und warten, dann von vorne
nein->aktion machen, dann eigene löschen und von vorne
geht nicht!
Stell dir einfach mal vor, jeder prozess macht genau das gleiche:
DateiA | DateiB
DateiB existiert | DateiA existiert
DateiA löschen | DateiB löschen
und von vorne -->Keiner macht was außer warten und HDD kaputt
UND: Du hast mehrere PHP instanzen! Das musst du u.U. auch beachten.
|
|
Sinspin
      
Beiträge: 1338
Erhaltene Danke: 120
Win 10
RIO, CE, Lazarus
|
Verfasst: Di 29.06.10 12:47
Tot laufen tu sich das bei der von mir beschriebenen Weise nicht. In meinem ersten Post habe ich beschrieben in welcher Art beide agieren müssen. Da rede ich zum einen von der doppelten Prüfung und von Wartezeiten nach einem Fehlschlag. Des Weiteren ist es sinnvoll wenn der Schreiberling nach getaner arbeit eine kleine Pause einlegt. Das machst du ja über den Timer. Musst halt mal schauen das der nicht zu of feuert.
Aber es gibt ja noch mehr Möglichkeiten.
Du könntest zum Beispiel mit zwei Bilddateien arbeiten. Dein Programm erstellt als ertes ein A-Bild und dann ein B-Bild.
Dein Script testet immer ob das B-Bild vorhanden ist. Liest das A-Bild und löscht es. Somit wird dann das B-Bild zum neuen A-Bild.
Dein Programm sieht nun nur noch das Neu A-Bild und erstellt ein neues B-Bild.
Beim "werden" von B zu A darf die Datei aber nicht umbenannt werden.
@ Flamefire:
Das sollte besser Funktionieren. So hat man auch gleich die Synchronisation mit an Board.
_________________ Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?
|
|
Flamefire
      
Beiträge: 1207
Erhaltene Danke: 31
Win 10
Delphi 2009 Pro, C++ (Visual Studio)
|
Verfasst: Di 29.06.10 13:58
@SinSpin: Doch tut es. Und zwar genauso wie ich es beschrieben habe. Wenn die Programm z.b. echt parallel laufen und zwar so wie ich es geschrieben habe, dann blockiert es (ist zugegeben ziemlicher Zufall, aber zumindest eine größere Verzögerung ist denkbar)
Deine Variante mit den 2 Bildern ist da schon besser. Hat aber einen gravierenden Nachteil:
Zeit Aktion
0 Program schreibt A und B
1 Leser liest und löscht A
2 Programm schreibt A
3..10 Leser verzögert sich (Lag)
11 Leser list B (was 11 Zeitschritte zurückliegt)
12 Schreiber B
13 Leser liest A was 13 Zeitschritte zurückliegt
Außerdem ist das Problem von mehreren Lesenden nicht behoben...
Vorschlag:
Programm schreibt zyklisch min. 3 Dateien:
Datei1 schreiben, Read1 erstellen
Datei2 schreiben, Read2 erstellen, Read1 löschen
Datei3 schreiben, Read3 erstellen, Read2 löschen
usw.
Sprich: Nach dem erstellen der Dateix wird eine Readx Datei erstellt, die dem Leser sagt, es kann die Dateix lesen.
Nach dem Erstellen von Readx wird die Datei Read(x+2) (also die übernächste) gelöscht.
Da Lesen schneller geht als schreiben, sollte so sichergestellt sein, dass selbst im ungünstigstem Fall, die Datei noch gelesen werden kann, bevor sie überschrieben wird.
100% Sicher ist es nicht aber mit x->unendlich geht die Sicherheit->100%
Mehr Dateien=Mehr Verzögerung. Darum würde ich 3 vorschlagen. Eine neue wird mit 3/4 der Zeit erstellt, die das Internetprogramm zum Update braucht. Dann ist die verzögerung minimal.
Beste Lösung: PHP schickt Anfrage an Programm (z.b. per HTTP request oder DLL/externes Programm) mit zufälligem Dateinamen. Programm macht Screenshot, php liest und löscht die Datei.
|
|
|