Flash XML Socket und Perl Socket Server

Flashs XMLSocket-Klasse in Verbindung mit Perl-Sockets

Mit Perl ist viel mehr möglich als „nur“ dynamische Webseiten zu erstellen, auch auf die Socket-API von C lässt sich darauf zugreifen und in Verbindung mit Flash als Client lassen sich damit Chats und sogar Multiplayer-Spiele realisieren. Was ist ein Socket? Um es kurz zu machen: ein Socket ist eine Schnittstelle in einem Netzwerk, die es ermöglicht Daten beinahe in Echtzeit zu übertragen. Dabei fungiert ein Perl-Script als zentraler Server, lauscht auf Verbindungen und eingehende Daten, parst die Daten und sendet sie bei Bedarf weiter an andere Computer, die auch mit dem Perl-Server verbunden sind.
Zum Vergleich: ein Apache-Webserver macht eigentlich das selbe. Er lauscht auf sogenannte HTTP-Requests, die wir senden, wenn wir einen Link anklicken. Der Webserver parst die Daten und liefert uns die gewollte Seite aus. Der vorteilhafte Unterschied zwischen einem Apache-Webserver und einem Perl-Socket-Server liegt aber darin, dass es nicht ganze HTML-Seiten sind, die über die Leitungen fließen, sondern schlanke Strings.

Kleines Beispiel: Wir klicken einen Button in Flash an, auf dem steht: Zeig mir die Server-Zeit.
Flash sendet durch einen (TCP-)Socket den String „[aktion:serverzeit]\0“ an den Perl-Socket-Server. Das „\0“ fügt der Flash-Player übrigens automatisch hinzu, um damit das Ende des Strings zu signalisieren.
Der Perl-Server parst den String und findet heraus: aha, ich soll die Serverzeit ausliefern. Als Antwort schickt er nun den String „[serverzeit:12:32:54]\0“.
Es sei an dieser Stelle auch gleich erwähnt, dass die XMLSocket-Klasse nicht zwingend Strings im XML-Format verlangt. Und das ist auch gut so, denn ein
„<xml version=“1.0“><aktion>serverzeit</aktion></xml>“ im vergleich zu „[aktion:serverzeit]“ ist ganz klar bandbreitenschonender, weil man einfach viel weniger Daten senden muss. Natürlich hätte ich auch „{aktion}{serverzeit}“ schreiben können oder auch „[a][s]“ oder gar „[s]“. Welches Protokoll man auch verwendet, solange man es selbst versteht und solange es logisch ist, passt alles.

Perl, der Meister der Regular-Expressions. Damit wird es sehr einfach, die Daten zu parsen.

$flashDaten =~ /\[aktion:(\w+)\]/;
my $aktion = $1;

if ($aktion eq „serverzeit“) {
my ($sec,$min,$hour) = localtime(time);
my $anwort = „[serverzeit:$hour:$min:$sec]\0“;
sende_zurück($antwort);
}

Ok, ich glaube man hat mich verstanden: Sockets dienen hauptsächlich dazu möglichst kleine Daten möglichst schnell zu senden/empfangen, und bieten damit die Möglichkeit viele Clients gleichzeitig zu bedienen. Man stelle sich einen Chat vor auf dem sich gerade hunderte User unterhalten. Die Nachrichten müssen so schnell wie möglich weitergeleitet werden, um überhaupt einen Chat möglich zu machen. Es reicht nicht, die Nachrichten in einer Datenbank zu speichern und alle paar Sekunden mittels eines HTTP-Requests die Seite zu aktualisieren. Es gibt zwar solche Chats, z.B. mit PHP, MySQL und Javascript (für automatische HTTP-Requests) realisiert – aber die taugen doch nicht wirklich was; und zwingen mit steigender Useranzahl selbst die stärksten Server in die Knie.

Ein ganz nützliches Perl-Modul, mit dem die Arbeit mit Sockets zum Kinderspiel wird, ist das POE-Modul. POE heisst Perl Object Environment, es ist objektorientiert und dadurch ist die Syntax auch leicht verständlich.

Was ist POE? POE ist ein Framework, welches es wie ein Betriebssystem erlaubt, mehrere Prozesse in einem Perl-Skript gleichzeitig laufen zu lassen, über sogenannte Sessions. Es lassen sich damit wunderbare Programme schreiben, in denen verschiedene Sessions sich um verschiedene Aufgaben kümmern. Da es für viele Bereiche – vor allem im Netzwerk-Bereich – vorgefertigte POE-Module gibt, schreibt sich ein Socket-Server damit fast schon von alleine. Die Hauptarbeit überlassen wir einfach POE und können uns direkt um die lustigen Sachen kümmern wie die Logik unseres Servers, Datenparsen usw.

Ladet euch das POE-Framework von CPAN herunter und installiert es. Falls ihr keinen eigenen Server habt sondern einen Webspace ohne Root-Zugang, kein Problem. Erstellt einfach einen Ordner auf dem Webspace, ladet dort das POE-Modul hoch und inkludiert es anstatt einfach nur:

use POE;

mit…

use lib „dein/absoluter/pfad/zum/POE-Ordner/lib“;
use POE;

Nun aber endlich mal zu einem Beispiel. Ich zeige euch einen kompletten Perl-Socket-Server, der eigentlich zwei Server beinhaltet: der eigentliche Hauptserver kümmert sich um den Flash-Film, der andere Server – nennen wir ihn Policy-File-Server – kümmert sich um die Auslieferung einer virtuellen XML-Datei, dem sogenannten Policy-File. Policy-File, was ist das?
Nun ja, machen wir es kurz: Adobe verlangt aus Sicherheitsgründen die Auslieferung eines virtuellen Policy-Files, quasi eine Datei in der geschrieben steht, dass der Flash-Film dazu berechtigt ist auf bestimmte Ports des Servers zugreifen zu dürfen.
Diese Datei liegt in unserem Perl-Skript in einem String und wartet nur darauf, in die große weite Welt verschickt zu werden. Sie sieht, bei mir zumindest, so aus:

my $xml = ‘<?xml version=”1.0″?><!DOCTYPE cross-domain-policy SYSTEM “/xml/dtds/cross-domain-policy.dtd”><cross-domain-policy><site-control permitted-cross-domain-policies=”master-only”/><allow-access-from domain=”localhost” to-ports=”5006″ /></cross-domain-policy>’;

Wie man sieht, steht darin geschrieben, dass localhost auf den Flash-Film zugreifen darf, und der Flash-Film auf den Server auf Port 5006.

Auf Port 5005 lauscht ein zweiter Server, also eine zweite POE-Session, die sich um nichts anderes kümmert als auf eine Verbindung und einen String „<policy-file-request/>\0“.
Schickt ein Flash-Film – oder wer auch immer – solch einen String, bekommt er als Antwort die $xml-Datei.

Ladet euch einfach die Quelltexte für den Actionscript-Client und den Perl-Server herunter. Schaut euch mal die Datei testServer.pl an.

Ganz kurz, was der Hauptserver macht: Er lauscht auf Verbindungen, akzeptiert diese, schreibt die Verbindungen oder besser gesagt die Referenzen dazu in das Array @connections, sendet eingehende Daten an die Verbindungen (im Array @connections, ausser an den Sender), löscht beendete Verbindungen wieder aus @connections (das ist wichtig, damit der Server nicht versucht Daten an bereits beendete Verbindungen zu senden – was zu einem sehr unschönen Programmabbruch führen würde). Daten parsen tut er nicht, aber falls er das tun soll, könnte es etwa so aussehen wie schon oben erwähnt, mit Regular Expressions:

$buff =~ /\[aktion:(\w+)\]/;
my $aktion = $1;

if ($aktion eq „serverzeit“) {
my ($sec,$min,$hour) = localtime(time);
my $anwort = „[serverzeit:$hour:$min:$sec]\0“;
$outbuffer{$client} .= $antwort;
$kernel->select_write($client, „event_write“);
}

Nun zum Flash-Teil. Wir erstellen nun einen Flash-Film, der einfach ein blaues Viereck zeigt. Dieses Viereck lässt sich verschieben, und wenn man es verschoben hat, sendet es die neuen Koordinaten des Vierecks an die anderen Flash-Filme, die noch mit dem Server verbunden sind. Die anderen Flash-Filme platzieren das Viereck dann an der neuen Position.

Ich zeige erstmal den Actionscript-Code. Es ist übrigens möglich den Code via der freien Flex-SDK
zu kompilieren, falls man kein Flash besitzt. Und das schöne an der Flex-SDK ist – außer dass sie nichts kostet – dass man sie auch unter Linux einsetzen kann. Da POE unter Windows nur zu Versuchszwecken taugt (POE verursacht zumindest beim strawberry-Perl unter Windows nach kurzer Zeit eine CPU-Auslastung von 100%) ist das natürlich sehr praktisch.
Falls ihr an der Flex-SDK interessiert seit, benutzt Google, ist leicht zu finden.

Erstellt in Flash einen neuen Film, speichert ihn und gebt in den Eigenschaften als Dokumentklasse TestSocket an. Mit TestSocket ist die Datei TestSocket.as gemeint, die ihr zusammen mit dem neuen Flash-Film in den selben Ordner kopiert. Oder kopiert die AS-Datei in den bin-Ordner der Flex-SDK und kompiliert den Code mittles Eingabeaufforderung bzw. Terminal dort mit mxmlc TestSocket.as. Danach bindet ihr die SWF-Datei in eine HTML-Seite ein und ladet diese zusammen mit der SWF-Datei auf euren Webspace bzw. xampp bzw. /var/www/ oder wo auch immer ihr eure Webseiten liegen habt hoch.

Startet nun den Server mittels Terminal oder Eingabeaufforderung und ruft über den Browser die HTML-Seite mit dem Flash Film auf. Wenn alles geklappt hat, macht weitere Fenster oder Tabs auf und verschiebt das Viereck. Es müsste nun auf allen anderen Seiten ebenfalls verschoben worden sein.

Ach ja, ein besonderes Schmankerl für die eigene Webseite ist es natürlich einen unsichtbaren Flash-Film laufen zu lassen, der eine Socket-Verbindung herstellt. So ist ein Datenaustausch auch ohne Seitenreload möglich. Dabei kann man Javascript als Brücke verwenden, um so empfangene Daten direkt im Browser auszugeben bzw. anzuzeigen. Man stelle sich einfach vor, dass ein User namens „Hans“ dem User mit der Uid 12 eine Nachricht schreibt, ganz normal über die Webseite. Nun wird eine Funktion in Javascript aufgerufen, die dem Flash-Film sagt, er soll eine Nachricht an den Server schicken, z.B. „[post][12][Hans]“. Der Server parst diesen String und findet heraus: aha, ich soll dem User 12 Bescheid sagen, dass er soeben Post von Hans bekommen hat. Der Server schickt an den Socket des Users 12 den String „[post][Hans]“.
Nun erscheint am rechten unteren Bildschirmrand des Postempfängers – der ja noch nichts von seinem Glück weiß, weil er die Seite noch nicht aktualisiert hat – eine kleine schicke Box, in der steht: „Sie haben Post von Hans!“. Posteingang-Benachrichtigung ohne Seitenreload beinahe in Echtzeit, realisiert mit einem TCP-Socket.

Sehr vorteilhaft ist es natürlich diesen unsichtbaren Flash-Film in einer Hauptseite laufen zu lassen, in der die eigentlichen Webseiten in einem iframe dargestellt werden. Warum? Weil sonst bei jedem neuen Seitenaufruf die Verbindung unterbrochen und dann wieder hergestellt wird.

Es gibt übrigens eine Javascript-Klasse, die diese Brücke herstellt, gebt mal in einer Suchmaschine „JSXML Bridge Javascript Flash“ ein. Diese Klasse arbeitet mit der ExternalInterface-Klasse von Flash.

Zuguterletzt noch zwei Punkte:
1.Warum muss ich jeden String, den ich vom Perl-Socket-Server an einen Flash-Client schicke mit einem „\0“ beenden? Weil Flash sonst ewig auf das Ende der Nachricht warten würde.
2.Kann jedes Programm, dass Socketverbindungen möglich macht, von jedem anderen Menschen dazu benutzt werden meine auf Port 5005 und 5006 lauschenden Server mit Nachrichten geradezu zu überfluten? Und ob. Stichwort Flooding. Leider können die Server nicht erkennen, ob Daten von einem Flash-Film, einem C++-Programm, einem anderen Perl-Skript oder von sonstwo geschickt werden. Hier ist es wirklich sehr wichtig, sich sichheitstechnisch abzusichern, will man nicht von seinem Webhoster gesperrt werden. Ich z.B. habe es so realisiert, dass nachdem sich ein User in meine Webseite eingeloggt hat seine IP-Adresse über einen UNIX-Socket an das POE-Skript gesendet wird; diese IP-Adresse wird für ein paar Sekunden erlaubt, d.h. Nur IP-Adressen werden gestattet, die praktisch „von oben“ ein okay bekommen haben, und das nur für ein paar Sekunden. Jede andere IP-Adresse wird gar nicht erst reingelassen bzw. sofort wieder rausgeworfen. „Tut mir leid, sie stehen nicht auf der Gästeliste!“. Ausserdem muss der Client auch seine Session-ID mitschicken, und es wird geprüft, ob diese in der Datenbank unter den eingeloggten Usern steht. Wenn nicht, auf Wiedersehen.

Okay, und das ist auch das Stichwort für mich, ich muss weg. Ich hoffe ich konnte dem einen oder anderen einen groben Einblick in die Welt der Sockets bieten und wünsche euch viel Spaß beim Erstellen von coolen Flash-Perl-Applikationen.

Über mighty.marcus

Ich bin anders.
Dieser Beitrag wurde unter Programmierung abgelegt und mit , , , , , , verschlagwortet. Setze ein Lesezeichen auf den Permalink.

3 Antworten auf Flash XML Socket und Perl Socket Server

  1. Vor allem ohne Javakenntnisse Mit Flash funktioniert das ja dann wohl so hnlich oder? Damals ging es nur darum eine Mglichkeit zu schaffen dass man ber den Browser augenblicklich benachrichtigt wird wenn eine neue Nachricht eingeht ging um ein Feature fr eine Auktions-Maschine und wie es scheint knnte ich das mit Java oder Flash machen daran hatte damals keiner gedacht! 2002 16 32..holla again Mit Flash funktioniert das ja dann wohl so hnlich oder?

  2. Mit Java ist es sogar noch leichter, weil man keinen “Policy-File-Server” braucht wie bei Flash. Mann muss eigentlich nur einen Java oder Flash-Client schreiben, sprich eine Socketverbindung zum Server aufmachen und die empfangenen Daten Javascript übergeben, mit dem man dann den DOM aktualisieren kann.

  3. Und einen Perl, Ruby, Python, PHP oder Java Socketserver…

Hinterlasse eine Antwort

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *

*

Du kannst folgende HTML-Tags benutzen: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">

fruit
Was ist das?*