Socket Server Problem

Hallo Experten!

Ich versuche, skriptgesteuert eine Socket Server Instanz zu erzeugen. Nachstehend ein Ausschnitt des Skripts.


function GetModuleId($moduleName)
{
	foreach (IPS_GetModuleList() as $moduleId)
	{
		$module = IPS_GetModule($moduleId);
		if ($module['ModuleName']==$moduleName) return $moduleId;
	}
	return '';
}

...

   $socketServer = IPS_CreateInstance(GetModuleId('Server Socket'));
   IPS_SetName($socketServer,'Telnet Server');
   SSCK_SetPort($socketServer,23); // default Telnet Port
   SSCK_SetLimit($socketServer,4); // maximal 4 clients gleichzeitig
   SSCK_SetOpen($socketServer,true); // Port öffnen

...

Die Instanz wird auch korrekt angelegt, aber aus unerfindlichem Grund nicht geöffnet. Im Objektbaum wird sie als geschlossen angezeigt.

Gehe ich jetzt durch Doppelklick in das Konfigurationsfenster der Instanz, so ist aber ein Häkchen bei „Öffne Server“ gesetzt. Verlasse ich die Konfiguration mit ok, ist der Server dann auch geöffnet. Nur wollte ich diese manuelle Aktion vermeiden.

Habe ich was falsch gemacht oder ist es ein Bug?

Viele Grüße
Andreas

IPS_ApplySettings wird dir fehlen :slight_smile:

paresy

Danke für den Tipp. Funzt jetzt.

Hallo paresy,

kaum läuft der Server, schon kommen Fragen auf. Ich habe im Moment folgende Konfiguration:

Server Socket auf Port 23
Register Variable verbunden mit Server Socket triggert ein Skript, wo ich die Daten über $IPS_VALUE auslese.

Wenn ich mich mit einem TelnetClient auf den Server verbinde, klappt auch alles, d.h. Keystrokes landen in meinem Skript und ich kann auch Terminalausgaben mittels SSCK_SendText() machen:).

Nun zu den Fragen:confused::

  1. Gibt es eine Möglichkeit, dass der Server Socket bereits beim Öffnen der Verbindung durch den Client ein Skript triggert? Im Moment passiert das erst, wenn der Client Zeichen an den Server sendet. Ich würde aber gerne ein Prompt ausgeben, sobald sich der Client verbunden hat.
  2. Der Server Socket erlaubt ja (per Konfiguration) mehrere parallele Verbindungen. Gibt es eine Möglichkeit im Skript herauszufinden, über welche Verbindung die Daten hereingekommen sind?
  3. Gibt es entsprechend beim Senden über den Server Socket die Möglichkeit, festzulegen auf welcher Verbindung die Daten gesendet werden sollen? Im Moment gehen sämtliche gesendete Daten an alle verbundenen Clients.
  4. Kann man im Skript, das von einer Register-Variable über „Benutze Skript“ aufgerufen wird, feststellen, welche Registervariable das Skript getriggert hat?

Viele Grüße

Ich habe noch folgenden Fehler in meinem Skript und finde keine Lösung.
Hier der relevante Ausschnitt aus dem Skript


...
  $socketServer = IPS_CreateInstance(GetModuleId('Server Socket')); 
   IPS_SetName($socketServer,'Telnet Server'); 
   SSCK_SetPort($socketServer,23); // default Telnet Port 
...

Was geschieht nun?
Wenn sich bereits zuvor irgendeine Instanz vom Typ Server Socket im Objektbaum befindet, läuft alles gut.

Wenn aber die über das Skript erzeugte Instanz die erste dieses Typs ist, steigt das skript bei SSCK_SetPort() aus, weil die Funktion nicht definiert ist. Mit dem Erzeugen der Instanz hätte sie doch eigentlich zur Verfügung stehen müssen, nur weiß vermutlich die PHP Umgebung noch nichts davon.

Gibt es eine IPS-Funktion, die ich vor SSCK_SetPort() aufrufen sollte, um die Funktion dynamisch zu laden?
Habe schon viel probiert, aber weder in der Doku noch im Forum finde ich eine Hinweis.

Gruß
Andreas

Ich tippe nun einfach mal:
hast Du vor dem „SetPort“ mal ein „IPS_ApplySettings“ probiert?

Gruß
dfhome

Ja, habe ich schon gemacht. Ändert nichts. Das ApplySettings() ist nach der kompletten Konfiguration notwendig, damit die Konfiguration auch tatsächlich abgespeichert wird.

Hier nochmal ein etwas längerer Ausschnitt aus dem Skript.

   
   $socketServer = IPS_CreateInstance(GetModuleId('Server Socket')); 
   IPS_SetName($socketServer,'Telnet Server'); 
   IPS_ApplySettings($socketServer); // Hilft Nichts!
   SSCK_SetPort($socketServer,23); // default Telnet Port, hier Fehler, wenn nicht bereits vorher eine Socket Server Instanz existierte 
   SSCK_SetLimit($socketServer,4); // maximal 4 clients gleichzeitig 
   SSCK_SetOpen($socketServer,true); // Port öffnen 
   IPS_ApplySettings($socketServer); // Einstellungen speichern

Fällt dir noch was anderes ein?
Viele Grüße

Die Antworten werden dir zwar nicht gefallen… hier sind sie aber:

  1. Gibt es eine Möglichkeit, dass der Server Socket bereits beim Öffnen der Verbindung durch den Client ein Skript triggert? Im Moment passiert das erst, wenn der Client Zeichen an den Server sendet. Ich würde aber gerne ein Prompt ausgeben, sobald sich der Client verbunden hat.
  2. Der Server Socket erlaubt ja (per Konfiguration) mehrere parallele Verbindungen. Gibt es eine Möglichkeit im Skript herauszufinden, über welche Verbindung die Daten hereingekommen sind?
  3. Gibt es entsprechend beim Senden über den Server Socket die Möglichkeit, festzulegen auf welcher Verbindung die Daten gesendet werden sollen? Im Moment gehen sämtliche gesendete Daten an alle verbundenen Clients.

Nein zu allen 3 Punkten. Da ich das aber sehr Interessant finde, könnte ich vielleicht etwas anderes dafür Zaubern. Aber erst nach dem Wochenende.

  1. Kann man im Skript, das von einer Register-Variable über „Benutze Skript“ aufgerufen wird, feststellen, welche Registervariable das Skript getriggert hat?

Nein. Da könnte ich aber ohne riesen Aufwand etwas ändern.

Wenn aber die über das Skript erzeugte Instanz die erste dieses Typs ist, steigt das skript bei SSCK_SetPort() aus, weil die Funktion nicht definiert ist. Mit dem Erzeugen der Instanz hätte sie doch eigentlich zur Verfügung stehen müssen, nur weiß vermutlich die PHP Umgebung noch nichts davon.

Leider ist das nicht der Fall. Erst wenn die PHP Engine neu gestartet wurde (quasi wenn alle andere Skripte zum Ende gekommen sind), sind die neuen Befehle im System drin. Du könntest versuchen nach dem IPS_CreateInstance ein Fork des Skriptes über IPS_RunScript zu starten. Dieser müsste dann erst nach dem Engine Restart ausgeführt werden. Mit IPS_RunScriptEx kannst du dir auch einen Parameter mit übergeben.

paresy

Hallo Paresy,

Danke für die Antworten.

Du könntest versuchen nach dem IPS_CreateInstance ein Fork des Skriptes über IPS_RunScript zu starten.

Das ließ sich mit IPS_RunScript(Ex) leider nicht lösen, da wohl das geforkte Skript ausgeführt wird vor dem Rebuild der Engine. Ich habe es mit einem Timer gelöst:).

Zu den anderen Themen ein paar Anregungen:rolleyes::
Das Problem mit mehreren Verbindungen könnte man vielleicht so lösen, dass man mehrere Server Socket Instanzen auf den gleichen Port setzt, die jeweils eine Verbindung zulassen. Wenn ein Client sich verbindet, wird irgendeine freie Server Instanz ausgewählt, die dann die Verbindung behandelt. Dieser Ansatz hätte den Vorteil, dass man den Open/Close Status der Verbindung über eine Statusvariable der Server Socket Instanz abbilden kann. Wenn dagegen mehrere Verbindungen von einer Instanz behandelt werden, muss man ja für jede Verbindung den Status verfolgen.

Ein zweiter Ansatz wäre, dass sich mehrere Registervariablen auf den Server Socket verbinden können. Der Server Socket ordnet dann intern jeder TCP-Verbindung eine Registervariable fest zu. Open/Close Information müsste dann im Zusammenspiel zwischen Register Variable und I/O Instanz geschehen. Wenn es irgendetwas über den Status der I/O Verbidung zu signalisieren gibt (hier TCP-Verbindung, könnte aber generisch für andere I/O Verbindungen ebenso funktionieren), würde die Registervariable beim Aufruf des angebundenen Skripts dies in einer Umgebungsvariable ($IPS_IOCTL) signalisieren. $IPS_VALUE wäre dann z.B. ein leerer String.

Bin gespannt, was da von dir kommt.
Viele Grüße