Binärdaten über Websockets verschicken

Über Websockets kann man Binärdaten verschicken, leider ist dies nicht ganz so einfach wie es sein sollte. Das erste Problem ist, das es in JavaScript bis vor einiger Zeit keine „Binärtypen“ gab. Aber dank einiger Dinge ist es mittlerweile möglich Binärdaten per JavaScript und Websockets zu versenden. Mein Problem an der binären Datenübertragung war bisher, das es augenscheinlich nirgens ein komplettes Beispiel gibt, welche diese einfach mal demonstriert. Dabei ist das ganze relativ einfach:

<!DOCTYPE html>
<html>
  <head>
    <title>Websocket Binary Test</title>
    <meta charset="utf-8" />
  </head>
  <body>
    <script type="text/javascript">
      websocket = new WebSocket("ws://echo.websocket.org");
      websocket.binaryType = "arraybuffer"; //Binärtyp auf arraybuffer setzen

      //OnOpen verdraten
      websocket.onopen = function (e) {
        //Array zusammenbauen
        var message = new ArrayBuffer(9);
        var dataViewMessage = new DataView(message);

        dataViewMessage.setInt8(0, 25); //Command ID
        dataViewMessage.setInt16(1, 11); //Account ID
        dataViewMessage.setInt32(5, 43333020); //Anzahl der Credits

        //message per Websocket wegschicken
        websocket.send(message);
      }

      //OnMessage verdraten
      websocket.onmessage = function (wsPackage) {
        //Datentyp ermitteln
        if(wsPackage.data instanceof ArrayBuffer) alert("ArrayBuffer");
        else if(wsPackage.data instanceof Blob) alert("Blob");
        else if(typeof wsPackage.data === "string") alert("string");

        //Daten empfangen und auseinander bauen
        var dataViewPackage = new DataView(wsPackage.data);
        alert(dataViewPackage.getInt8(0));
        alert(dataViewPackage.getInt16(1));
        alert(dataViewPackage.getInt32(5));
      }
    </script>
  </body>
</html>

Im den ersten Zeilen im Skriptteil wird zuerst ein Websocket angelegt, welches sich mit „ws://echo.websocket.org“ verbindet. Dieser Server gibt immer genau das zurück was er empfängt und eignet sich somit ausgezeichnet für diesen kleinen Test.

Danach wird der „binaryType“ des Websockets auf „arraybuffer“ gesetzt, da wir mit einem solchen arbeiten wollen. In der verknüpften „OnOpen“ Methode wird ein „ArrayBuffer“ mit der passenden Größe angelegt und mit diesem ein „DataView“ initialisiert. Mit diesem ist es dann möglich problemlos möglich die entsprechenden Werte in den „ArrayBuffer“ zu setzen.

Dies geschieht dann mit den Zeilen:

dataViewMessage.setInt8(0, 25); //Command ID
dataViewMessage.setInt16(1, 11); //Account ID
dataViewMessage.setInt32(5, 43333020); //Anzahl der Credits

Am Ende wird das ganze weggeschickt und anschließend wieder in der „OnMessage“ Funktion empfangen. Dort wird der Datentyp ermittelt (für den Fall das man mit mehreren Typen arbeitet) und anschließend wird das Paket wieder Binär auseinander genommen.

Weitere Informationen gibt es unter:
http://www.websocket.org/echo.html
http://www.html5rocks.com/en/tutorials/webgl/typed_arrays/
https://developer.mozilla.org/en-US/docs/JavaScript_typed_arrays
http://msdn.microsoft.com/de-de/library/br212463%28v=vs.94%29.aspx
https://developer.mozilla.org/en-US/docs/JavaScript_typed_arrays/ArrayBuffer
http://stackoverflow.com/questions/11390021/transferring-files-with-javascript-through-websockets

MooTools und benutzerdefinierte Events

Bei MooTools handelt es sich um ein Framework mit welchem man sehr schön Klassen basierte Strukturen in JavaScript abbilden kann. Bei der Definition von benutzerdefinierten Events ist die Dokumentation leider etwas dünn, so das ich dort etwas probieren musste, bis ich zum richtigen Ergebnis gekommen bin.

Gegeben sei dabei ein Projekt mit einer „index.html“ Datei sowie der JavaScript Datei „explosive.js“ welche die Klasse „Explosive“ enthält. Die Klasse sieht dabei im Quelltext so aus:

var Explosive = new Class({
       Implements: [Events],

       tntequivalent: 0,

       //Constructor
       initialize: function(equivalent) {
         this.tntequivalent = equivalent;
       },

       //Methods
       detonate: function(){
         this.fireEvent('explode');
       },

       detonateWithInfo: function(){
         this.fireEvent('explode', this.tntequivalent);
       }
});

In dieser Klasse gibt es die Eigenschaft „tntequivalent“ welche die Sprengkraft unser Bombe definiert und im Konstruktor gesetzt wird. Die Funktionen „detonate“ und „detonateWithInfo“ zünden die Bombe und senden das Event „explode“ wahlweise mit der Informationen über die Sprengkraft.

Die dazu passende „index.html“ sieht dabei so aus:

<!DOCTYPE html>
<html>
  <head>
    <title>Mootools Event Test</title>
    <meta charset="utf-8" />
    <script type="text/javascript" src="mootools-core-1.4.5-full-nocompat.js"></script>
    <script type="text/javascript" src="explosive.js"></script>
  </head>
  <body>
    <script type="text/javascript">
      function onExplode(object)
      {
        if(object==null)
        {
          alert("Bomb is exploded.");
        }
        else
        {
          alert("Bomb is exploded, with " + object + " tons of TNT equivalent.");
        }
      }

      var bomb = new Explosive(100);
      bomb.addEvent('explode', onExplode);
    </script>

    <form>
      <input type="button" value="Detonate bomb" onClick="bomb.detonate();">
      <input type="button" value="Detonate bomb with info" onClick="bomb.detonateWithInfo();">
    </form>
  </body>
</html>

Hier wird im JavaScript-Bereich der Klasse eine Funktion „onExplode“ angelegt, welche das Event am Ende entgegennehmen soll. Darunter wird eine Instanz der Klasse „Explosive“ mit dem Namen „bomb“ angelegt. Dieser Instanz sagen wir das dass Event „explode“ an die Funktion „onExplode“ weitergereicht werden soll.

Nun werden noch zwei Buttons definiert, welche die auslösenden Funktionen aufrufen. Einmal wird die Funktion „onExplode“ mit einem Parameter und einmal ohne aufgerufen. In diesem Parameter steckt in diesem Fall die Sprengkraft der Bombe, so das diese mit ausgegeben werden kann. Und schon ist man mit seinem ersten Event fertig.

Weitere Informationen gibt es unter:
http://de.wikipedia.org/wiki/MooTools

Testbasierte Entwicklung unter JavaScript

Wer testbasierte unter JavaScript betreiben möchte, stößt da auf eine Menge Frameworks wie z.B. Jasmine, welches für sich für „Behavior Driven Development“ eignet. Persönlich suchte ich allerdings ein Framework für ganz normales Unit-Testing aller xUnit.

Schlussendlich bin ich bei „Enhance JS“ gelandet. Mit dem Framework ist es möglich schnell eigene Tests zu schreiben, um die Funktionsfähigkeit der entsprechenen JavaScript Anwendung zu testen. Bei JavaScript ist dies bei größeren Projekten alleine schon wegen der dynamischen Typisierung von Vorteil.

Die Testausgabe von Enchange JS

Der Quelltext, des unter der Apache Lizenz stehenden Frameworks, ist dabei auf Github zu finden. Die offizielle Seite kann unter http://www.enhance-js.com besucht werden.

Weitere Informationen gibt es unter:
http://de.wikipedia.org/wiki/XUnit
http://de.wikipedia.org/wiki/Behavior_Driven_Development
http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks

sprintf für JavaScript

Eine der ersten Sachen welche ich in JavaScript vermisst habe, ist eine „sprintf“ bzw. eine „String.Format“ Methode. Aber JavaScript wäre nicht JavaScript wenn es dafür keine Lösung gäbe. Die Lösung hört in diesem Fall auf den Namen „javascript-sprintf“ und kann unter http://www.diveintojavascript.com/projects/javascript-sprintf bezogen werden. So sieht das ganze dann im Quelltext aus:

var tmp="123456";
sprintf('Ausgabe ist %s.', tmp);

In diesem Fall wird „Ausgabe ist 123456.“ ausgegeben. Neben dieser Möglichkeit gibt es noch einige andere Funktionen in der kleinen Bibliothek wie z.B. „vsprintf“ mit welcher auch Arrays ausgegeben werden können, welche in der Dokumentation auf der Seite erklärt werden.