PHP und die Socken...

Maik

Angesehenes Mitglied
Hallo!

Ich habe hier ein Problem mit PHP und seinen Socket Funktionen. Ich habe die Socket-Funktionen in dutzende Klassen eingearbeit und dann abgeleitet daher kann ich keine Quellen geben. Aber ich umschreib mal das Problem.

Ich habe Clients die mit fsockopen verbinden, mit einem 1 Sekunden Timeout (1 Sekunde reicht, da Client & Server auf dem selben Rechner liegen). Nach dem die Verbindung hergestellt wurde schickt der Client 1 Byte an den Server um sich zu identifizieren. Danach wartet er auf Befehle vom Server.

Also der Ablauf des Clients ist so:
  • Mit Server verbinden
  • Erkennungsbyte schicken
  • Auf Aufgabe warten
  • Aufgabe bearbeiten
Der Server verwendet stream_socket_server und wartet auf Lese-Aktivitäten mit stream_select. Wenn ein zu lesender Socket das Handle des Server hat, nimmt der Server einen neuen Client an mit stream_socket_accept. Der neue ClientSocket wartet wieder auf Lese-Aktivitäten und wenn Daten da sind liest er einfach die Daten aus (das Erkennungsbyte), danach vergibt er aufgaben.

Also der Ablauf des Servers:
  • Auf neuen Client warten
  • neuen Client annehmen
  • Erkennungsbyte vom Client lesen
  • Aufgabe übermitteln
So... nun das Problem. Ich lasse 10 Clients und den Server laufen, mit einer Testausgabe vor stream_select will ich sehen wieviel Client-Sockets der Server hat. Da stellt sich nun heraus, dass obwohl nur 10 Clients laufen, ich teilweise wesentlich mehr Client Sockets habe. Es ist in meiner Liste aber kein doppelter Client-Socket-Handle, also sind es alles unterschiedliche Verbindungen.
Nun nach vielen Tests bin ich soweit, dass ich festgestellt habe, das die Sockets die zuviel sind, nur mit stream_socket_accept angenommen wurden, aber danach ist nichts damit passiert. Es wurde noch nicht mal der Lesebefehl ausgeführt. Das heißt, vom Client wurde nicht in die Verbindung geschrieben.

Eine konkrete Lösung wird es ohne Quelltext nicht geben. Es muss doch einen Grund geben warum ein Socket angenommen wird, aber von dem danach keine Aktion mehr kommt. Und ohne von einem Socket zu lesen bekommt man ja dummerweise auch nicht mit, ob es den Socket noch gibt.

Hätte evtl. irgendjemand einen Verdacht?
 
Vager Verdacht, da ich ja nicht mit PHP (und schon gar nicht mit Sockets) arbeite:

QUOTE Der Socket-Deskriptor, der von socket_accept() zurückgegeben wird, soll nicht dazu benutzt werden, um neue Verbindungsanforderungen zuzulassen. Der ursprüngliche wartende Socket socket bleibt geöffnet und kann wiederbenutzt werden.


Quelle: http://de.php.net/manual/de/function.socket-accept.php

Das scheint mir eine denkbare Quelle von zu vielen offenen Sockets zu sein.

PS: Ich tippe mal, daß 'wesentlich mehr' heißt, daß bei bsp. 10 Clients nicht genau 20 Sockets, sondern 'richtig viel mehr' da sind.
 
nein mit wesentlich mehr meinte ich, bei 10 Clients sind es nicht genau vielfaches von 10 sondern es variiert zwischen 10 (was korrekt ist) und 17... aber ich denke im ungünstigsten Fall könnten es auch bis zu 20 werden.

Ich schau mal nach zu dem "..._accept"...
 
Wenn ich das recht verstehe, bedeutet das nur, dass man socket-accept nur auf den Server-Socket anwenden kann, aber nicht auf einen bereits akzeptierten ClientSocket. Also so etwas würde nicht gehen:

CODE
$neuerSocket = socket_accept($ServerSocket);

... beliebiger Code ...

$nocheinSocket = socket_accept($neuerSocket);



Das mach ich ja auch nicht. Hier die Kurzfassung von dem wie ich es mache:


CODE
$readList = $AlleMeineClientSocketHandles;
$readList[] = $ServerSocketHandle;

if (@stream_select($readList, $w = NULL, $e = NULL, $timeout) === false)
return false;
else {
foreach($readList as $a_client) {
if ($a_client === $ServerSocketHandle) {
$neuerSocket = stream_socket_accept($a_client);
if ($neuerSocket!==false) {
// neue ClientSocket-Klasse erstellen
// mit dem Handle $neuerSocket
}
}else{
// vom ClientSocket $a_client lesen
}
}
}



Das ist die Hauptschleife, von der aus wird entschieden was gemacht werden muss.
 
Hat sich herausgestellt, dass es wohl ein PHP Bug war, nach einem Update von PHP war der Fehler weg.
 
Zurück
Oben