Sockets: Daten an Client versenden

pHoEnIx-sTyLe

Registered User
Hi,

also ich habe vor einen Socket-Server per PHP zu realisieren. Habe mir zu diesem Thema auch schon einiges durchgelesen, im PHP-Manual, sowie in diversen Artikeln per google. Nur aus einigen Dingen bin ich nicht ganz schlüssig geworden.

Zuerst mal für was der Socket-Server gedacht ist:
Der Socket Server soll mit bis zu ca. 2000 Usern/Clients eine persistente Verbindung per Streaming aufbauen. Der Client an sich muss keine Daten über diesen Socket verschicken. Es geht viel mehr darum, dass dieser Daten vom Server empfängt, welche über andere Script versendet werden. Mit diesen Daten soll der Client bestimmte Dinge tätigen.

Den Socket Server an sich zu erstellen ist kein Thema. Dazu finden man genug im Internet.
Was mich jedoch interessiert ist folgendes:

1) Wie kann der Client prüfen ob er Daten empfängt? Also es muss ja auch eine Funktion oder ähnliches geben. Muss der Client dann auch über socket_read() arbeiten? Wenn ja welche anderen Socket "eigenschaften" müssen vorher erstellt werden?

2) Wie kann ich dem PHP-Server genau sagen: Schicke an Socket an dem der Client mit IP: 123.456.789.34 sitzt?

Ich hoffe das ist so möglich und ich hab hier nichts verwechselt. Schonmal danke im voraus für eure Hilfe ;)
 
Du hast ein kleines aber wichtiges Detail ausgelassen:
Soll es ein TCP- oder UDP-Server werden?

Von Deiner Beschreibung (Server baut Verbindung auf, bzw. soll was schicken) klingt es nach UDP.

Aber eigentlich denke ich, Du willst TCP (denn UDP ist nicht persistent). Und dann mußt Du erstmal umdenken:
Nicht der Server baut die Verbindung auf, sondern der Client.
(Denn sonst wären die anderen die Server und Dein beschriebenes Teil ein Client.)
Der Server muß sich dazu pro Verbindung forken.
Damit hat jeder Thread/Child genau eine Verbindung zu einem Client.

Weitere Fragen?

huschi.
 
Erstmal danke für die Anwort. ;)
Hmm.. Ok da bringst du mich auf eine Idee. Ich bräuchte nicht unbedingt eine persistente Verbindung. Es ist einfach so, dass die Clients sich auf der Website befinden und irgendwann kommt durch ein Hintergrundprogramm eine Anweisung die der Client ausführen soll. Dazu sollen die Daten dem Client übermittelt werden und der Client stößt eine Aufgabe an die nur ihn selbst betrifft (Also es wird per AJAX etwas dynamisch nachgeladen).

Ist es in diesem Falle möglich, dass das Hintergrundprogramm diese Aufgabe irgendwann anstößt und seine Daten an den Client übermittelt?

Diese Lösung würde sich doch erheblich auf die Performance auswirken und diese verbessern.
 
In der Regel wirst Du vom Server keine Verbindung zum Client aufbauen können, da viele Clients hinter NAT-Routern stehen oder durch Firewall-Techniken geschützt sind. Daher ist es notwendig, vom Client aus eine Verbindung zum Server aufzubauen und diese während der ganzen Zeit aufrecht zu erhalten, damit der Server hin und wieder Daten zum Client schicken kann.

Viele Grüße,
LinuxAdmin

PS: Ich glaube, dass es furchtbar schwierig wird, solche Applikationen mit PHP zu entwickeln...
 
Reden wir hier also von einer reinen Web-Application?
Dann sollten wir wohl weniger von Server und Client reden, sondern von Apache (IIS?) und Browser.

Das HTTP-Protokoll ist ein recht "einseitiges" Protokoll. Daher willst Du wohl einen eigenen Socket-Server basteln. Aber vielleicht wirst Du etwas konkreter, was Du bauen willst und welche Daten wann geliefert werden sollen.
Denn so könnten wir Dir alternative Vorschläge liefern.
Ansonsten verrennst Du Dich evtl. gerade in Problemen, die gar nicht wirklich existieren... :)

huschi.
 
@ LinuxAdmin: Ok das mit den Routern hatte ich nicht bedacht. Das würde dann doch zu problematisch werden. Das mit der Entwicklung der Applikation in PHP hab ich so auch schon von anderen gehört, aber da ich mich leider in C++ nicht auskenne oder in anderen Sprachen, würde ich es gerne in PHP lösen sofern das möglich ist.

@ Huschi: Das ist schwer zu erklären worum es sich da genau handelt. Ich programmiere an einem Browsergame. Da hier gewöhnlich viele Spieler online sind geht das stark auf die Belastung des Servers. Ich habe schon einiges optimiert und die Lösung die ich hiermit ansteuern will würde sehr viel an der Serverlast ändern.

Also in Kurzfassung:
Es gibt eine Oberfläche. Diese wird dynamisch durch Ajax nachgeladen. Also alles läuft so gesehen live ab. Ich baue jetzt z.B ein Gebäude und das wird um XUhr und XMin fertig. Genau zu dieser Uhrzeit soll das Gebäude für den User auf der Oberfläche erscheinen. Wann jeweilige Dinge passieren sollen regelt mein Hintergrundprogramm.
Im moment läuft das ganze mit Polling. Es wird immer in einer .txt Datei geprüft ob Daten vorhanden sind, wenn ja wird das jeweilige Modul nachgeladen. Wenn jetzt aber 500 Spieler gleichzeitig 2 sekündlich dieses Polling betreiben lastet das zu stark aus. Also dachte ich mit meiner angefragten Lösung dieses Problem beseitigen zu können.
Dass nur dann Daten an den User rausgehen wenn diese vom Hintergrundprogramm fällig sind.
 
Gut, ok, ich verstehe worum es geht.

Mögliche Überlegung:
Du sagst dem Client, wann er das nächste mal Pollen soll um neue Ergebnisse zu erhalten. Dieser behält sich die in einer Tabelle. Die geht er regelmäßig durch und wenn er irgendwo über die Zeit ist (oder genau drauf) dann pollt er.
Und damit er auf keinen Fall was wichtiges Versäumt pollt er zusätzlich alle X Minuten. (Könnte ja sein, daß neue Poll-Zeiten auf ihn warten oder sonstige Events.)

huschi.
 
Ja diese Überlegung hatte ich mir auch überlegt, aber ich müsste dann trotzdem in ziemlich kurzen Abständen Polling betreiben, denn sonst könnte es wirklich vorkommen dass er verschiedene Events "vergisst" die das Hintergrundprogramm je nach Ablauf neu berechnet.

Habe lang daran überlegt und mir schien die Socket Lösung die beste und am einfachsten zu realisierende.

Hab mich da auch in dem ersten Post zu dem Thema umständlich ausgedrückt was den Client und den Server angeht. Der Server lauscht auf einem Port und wartet auf ankommende Clients. Diese "registriert" er dann und forkt den Prozess und soll einen persistenten Stream aufbauen. Mir ist nur unklar wie der Client weiss wann er neue Daten empfängt. Also ich stelle mir das so vor, dass der Client durchgängig auch auf Nachrichten lauschen muss. Oder wie darf ich das vorstellen?
 
Dadurch ergeben sich 2 Probleme:
a) Du kannst mit JavaScript keine andere Socket-Verbindung auf machen.
b) Dieser Server muß auf einen Port lauschen, der normalerweise nicht von einer Firewall oder Router geblockt wird. (Port 80 geht schon mal nicht mehr... :) )

Eine weitere Lösung in diese Richtung:
Setzte Flash ein.
Dies kann ein unsichtbares (oder grafisches) Objekt sein. Braucht keine weiteren Funktionen ausser eben den Client-Funktionen um mit dem Server tatsächlich diese Verbindung herzustellen (und ggf. neu zu reinitialisieren) und auf Daten zu warten.
Auf der anderen Seite stellt er eine Art Poll-Server für JavaScript dar.

D.h. das JS pollt auf den Flash-Client. Und dieser kann tatsächlich einfach auf Input vom Server warten.

Weiteres bisher nicht angesprochenes Problem:
Irgendwann gehen Dir die Anzahl der möglichen Connections aus. Denn ein Server ist in der Hinsicht irgendwo beschränkt.
@all: Hat jemand gerade dazu Zahlen bei der Hand?

PS: Statt Flash könntest Du natürlich auch ein ActivX-Objekt nehmen. Wärst aber damit nicht mehr Kompatible zu anderen OS & Browsern.

huschi.
 
Dadurch ergeben sich 2 Probleme:
a) Du kannst mit JavaScript keine andere Socket-Verbindung auf machen.
b) Dieser Server muß auf einen Port lauschen, der normalerweise nicht von einer Firewall oder Router geblockt wird. (Port 80 geht schon mal nicht mehr... :) )

Das ist so kein Problem. Ich kann auf der Index seite ja die Socket-Verbindung schon aufmachen oder aber auch mit AJAX im Hintergrund auf der Internen Index Seite einen Request abfeuern und somit ein PHP-Script laufen lassen.
Für die Ports könnte man doch einen Port am Server freischalten. Der Client lauscht doch dann meines Wissens auf einem Port des Servers, sodass sein Router dass doch nicht abblocken sollte. Oder versteh ich das was falsch?

Eine weitere Lösung in diese Richtung:
Setzte Flash ein.
...
D.h. das JS pollt auf den Flash-Client. Und dieser kann tatsächlich einfach auf Input vom Server warten.
...
Statt Flash könntest Du natürlich auch ein ActivX-Objekt nehmen. Wärst aber damit nicht mehr Kompatible zu anderen OS & Browsern.

Ja Flash wäre eine Lösung, aber ich müsste meine Lösung dringend durchsetzen und ich habe keine Erfahrung in Flash. Deswegen habe ich auch AJAX gewählt.
Das mit dem ActivX-Objekt klappt bei meinen AJAX-Requests in den gängigsten Browsern. (Also: IE, Firefox, Safari, Opera). Nur Netscape an sich scheint damit nicht klar zu kommen. Wobei die Nutzung von Netscape doch auch sehr gering ist.

Weiteres bisher nicht angesprochenes Problem:
Irgendwann gehen Dir die Anzahl der möglichen Connections aus. Denn ein Server ist in der Hinsicht irgendwo beschränkt.
@all: Hat jemand gerade dazu Zahlen bei der Hand

Das wäre sehr hilfreich zu wissen.
 
mit AJAX im Hintergrund auf der Internen Index Seite einen Request abfeuern und somit ein PHP-Script laufen lassen.
Ja, kannst Du, bringt Dir aber nichts.
Denn wie schon gesagt:
a) Du kannst mit AJAX lediglich eine HTTP-Verbindung auf machen.
b) Du kannst mit AJAX erst auf Daten zugreifen, wenn der vollständige Response angekommen ist.
c) Selbst wenn, gibt es keine Sicherheit, daß die Meldungen nicht irgendwo zwischen gebuffert werden.
d) Irgendwann greift ein Timeout und beendet die HTTP-Verbindung oder das PHP-Script.
e) Und Dir gehen recht schnell die Sockets am Server aus (bei Apache: ServerLimit).

Das mit dem ActivX-Objekt klappt bei meinen AJAX-Requests in den gängigsten Browsern.
Damit war nicht das XMLHTTP-Objekt im speziellen gemeint, sondern ein eigenes selbst programmiertes.

Für Deinen Fall sähe ich die Sache mit dem Flash-Objekt noch am Sinnvollsten an.

huschi.
 
Für Deinen Fall sähe ich die Sache mit dem Flash-Objekt noch am Sinnvollsten an.

Kannst du mir denn Tipps dazu geben wie ich das genau realisieren kann?, denn ich kenne mich in Flash nicht aus. Oder kennst du einen Link der mir genau diese Lösung näher bringen kann?
 
Hallo zusammen,
ich habe eure Diskussion aufmerksam verfolgt. Vielleicht hilft mein Senf ja ein wenig weiter. Ich würde einen anderen Weg wählen. Meine Erfahrung hat gezeigt, dass solche "entfernten Aufrufe" weder mit PHP noch einer anderer Interpretersprache ausreichend zu realisieren sind.

Was spricht gegen eine Java RMI oder Java JMS Implementierung. Ein Java Serverkomponente ist schnell entwickelt. Und der Rest RMI/JMS ist dann nur noch Definitionsarbeit.

Gruß
Haggy
 
Back
Top