Blog Home  Home Feed your aggregator (RSS 2.0)  
Peter Nowaks Mobile Blog - .NET Compact Framework Komprimierung für HTTP Verbindungen (WebServices und statische und dynamische Webseiten)
Mobility on the Run
 
 Thursday, July 05, 2007

Hach, es ist einfach herrlich mit dem .NET Compact Framework zu arbeiten. Zugegeben, es ist manchmal müssig, da man nicht den Komfort genießt, den Programmierer mit dem .NET Framework zu Teil wird. Dafür, so finde ich, ist man viel näher an der Materie, wenn sich das eine oder andere selbst erstellen muss. Man kann so viel tiefer in die Materie eindringen.

Doch dies hat auch seine Schattenseiten, denn wenn man schon bei seinen Möglichkeiten eingeschränkt ist, so sollte man auch erwarten, daß zumindest diese Einschränkungen unterstützt werden.
So mag ich einfach nicht verstehen wollen, warum die im .NET 2.0 vorhandene Komprimierung nicht auch vom .NET Compact Framework unterstützt wird. Dabei unterstützt doch gerade das HTTP Protokoll in der Version 1.1 bereits die Komprimierung vom Protokoll her.

Gerade bei mobiler Datenkommunikation wäre es doch sinnvoll, insbesondere wenn es um Geschäftsanwendungen geht, Daten zu reduzieren:

  • Mobile Geräte besitzen meist nur (sofern keine weiteren Speicherkarten verwendet werden) einige wenige MB an freiem Arbeitsspeicher
  • Daten werden meist immer noch mittels schmalbandiger und nicht unbedingt günstiger GPRS-Verbindung ausgetauscht. Bei einigen MB an Daten kann es sich bereits daher schon lohnen eine Kompression einzusetzen.

Die genaue Kompressionsrate bei einem ZIP-Algorithmus lässt sich nicht genau definieren. Dies ist von den zu komprimierenden Daten abhängig. Generell lässt sich jedoch sagen, daß eine Kompression von ca. 50% - 60% real ist.

Natürlich muss man dabei auch in Kauf nehmen, daß durch Komprimierung die Performance einer Anwendung leidet, da der Prozess zur Komprimierung und Dekomprimierung ziemlich speicher- und prozessorintensiv ist.

Somit wird ein komprimierter Datenaustausch zwischen mobilen Client und Server nicht wirklich schneller, da die gewonnene Zeit hierbei für durch die Kompression/Dekompression verloren geht. Man spart jedoch Speicherplatz und ggfs. ein wenig Geld.

Nachfolgend wird daher dargestellt, wie sich diese fehlende Funktionalität nachrüsten lässt.

Teil 1: Der Server

Zu allererst ist es nötig dem Webanwendung / dem WebService die Komprimierung "beizubringen", respektive die Komprimierung im Webserver für aspx, asmx und Co zu aktivieren.
Dabei wird der ASP.NET Development Server ausser acht gelassen, da dieser für das hier beschrieben Szenario ungeeignet ist. Dieser unterstützt nämlich keinen Zugriff "von aussen" und kann daher nur Anfragen von localhost verarbeiten, was bei der mobilen Entwicklung leider nicht weiterhilft.

Möglichkeit 1: IIS 6 Komprimierung aktivieren.

Dieser englischsprachige Artikel beschreibt, wie die bereits im IIS 6 vorhandene Komprimierung für dynamische Inhalte (aspx, asmx und asp) aktiviert werden kann.
Vorteil: Alle auf dem Server befindlichen Webanwendungen und -dienste können von der Komprimierung profitieren. Werden jedoch einige dieser Webdienste von .NET Compact Framework Anwendungen verwendet, die diese Komprimierung nicht verstehen, kann dies u.U. böse Folgen nach sich ziehen.
Nachteil: Man benötigt einen entsprechenden Remotezugriff auf den Server, um diese Einstellung ermöglichen zu können. Weiterhin sollte man mit der Materie schon ein wenig vertraut sein.

Möglichkeit 2: anwendungsbasierte Komprimierung

Neben der zuvor beschriebenen Möglichkeit ist es auch möglich, lediglich für die entsprechende Webanwendung / den entsprechenden WebService eine Komprimierung zu verwenden.
Vorteil: Es sind keine Modifikationen an der Serveranwendung nötig, d.h. sie braucht nicht erneut kompiliert zu werden. Es reichen einfach einige Konfigurationsänderungen an der web.config und ein paar zusätzliche DLLs. Ein weiterer Vorteil ist, daß alle anderen Webanwendungen / WebServices auf dem gleichen Webserver hiervon unberührt bleiben.

Um dies zu ermöglichen verwenden Sie bspw. das HttpCompressionModule von blowery.org. Sie erhalten es dort sowohl für ASP.NET 2.0, als auch für ASP.NET 1.1 jeweils als Sourcecode, oder als bereits vorkompilierte Bibliotheken. Dabei gilt zu beachten, daß unter ASP.NET 2.0 System.IO.Compression zur Komprimierung verwendet wird, während unter ASP.NET 1.1 die Kompressionsbibliothek SharpZipLib verwendet wird. Hierzu jedoch später mehr.

Das HttpCompressionModule agiert als so genanntes HTTP Modul. Dieses verändert Daten entweder beim Empfang oder jedoch beim Versenden. In unserem Fall geschieht dies beim Versenden. Hierzu wird das unterstützte Encoding beim Empfang ermittelt, und, sofern der GZip- oder Deflate-Komprimierungsalgorithmus vom Client unterstützt wird, die Antwort vor dem Versenden an den Client noch mal durch einen Filter (also dem HTTP Modul) komprimiert.

Um HttpCompressionModule in Ihrer Webanwendung zu nutzen, entpacken Sie bitte folgende Dateien in das bin-Verzeichnis der Webanwendung / des WebServices aus dem heruntergeladenen Archiv:

  • blowery.Web.HttpCompress.dll
  • blowery.Web.HttpCompress.xml
  • ICSharpCode.SharpZipLib.dll
  • ICSharpCode.SharpZipLib.xml

Diese Dateien befinden sich im Verzeichnis "Example\bin" des genannten Archivs.

Danach editieren Sie bitte die web.config der Webanwendung / des WebServices um folgende Einträge:

  • Im Abschnitt <configuration> fügen Sie bitte den folgenden Inhalt hinzu:
    <!-- This chunk sets up the configuration section handler for blowery.webmodules/ -->
      <configSections>
        <sectionGroup name="blowery.web">
          <section name="httpCompress" type="blowery.Web.HttpCompress.SectionHandler, blowery.Web.HttpCompress"/>
        </sectionGroup>
      </configSections>
     
      <!-- config section for my http module -->
      
      <blowery.web>
        <!-- ...Here's an example on how to change the algorithm or compressionlevel...
          <compressionModule preferredAlgorithm="deflate|gzip" compressionLevel="high|normal|low"/>
    ...so, to use deflate by default, and high compression, you have to set the following line
    ...-->
        <httpCompress preferredAlgorithm="gzip" compressionLevel="high">
          <excludedMimeTypes>
            <add type="image/jpeg"/>
            <add type="image/gif"/>
          </excludedMimeTypes>
          <excludedPaths>
            <add path="NoCompress.aspx"/>
          </excludedPaths>
        </httpCompress>
      </blowery.web>
  • Im Abschnitt <system.web> fügen Sie bitte noch folgendes hinzu:
        <httpModules>
          <add name="CompressionModule" type="blowery.Web.HttpCompress.HttpModule, blowery.web.HttpCompress"/>
        </httpModules>

Ggfs. ist noch ein Neustart des Webservers nötig, den Sie beispielsweise leicht mittels auf der Kommandozeile ausgeführten Kommando "iisreset" durchführen können.

Der erste dargestellte Abschnitt beschreibt die sectionGroup, welche von HTTPCompress verwendet wird. In dieser Sektion ("<blowery.web>") werden die Konfigurationseinstellungen für die Komprimierung definiert. Dabei ist sowohl der Komprimierungsalgorithmus (gzip oder deflate), als auch die Komprimierungsstärke (high, normal oder low) verwendbar.

Der zweite Konfigurationsabschnitt in "<system.web>" macht ASP.NET gegenüber dieses HTTP Modul bekannt, so daß es verwendet werden kann.

Teil 2: Testen der serverseitigen Komprimierung

Wenn Sie testen möchten, ob Ihr Daten nun korrekterweise komprimiert versendet werden, verwenden Sie doch einfach das kostenfreie und erweiterbare Microsoft Tool Fiddler.
Bei diesem Tool handelt es sich um einen HTTP Proxy (auch HTTP Debugging Proxy genannt), welcher sehr häufig von Webentwicklern eingesetzt wird. HTTP Proxy bedeutet in diesem Fall, das die über diesen Dienst durchgeschleust und aufgezeichnet wird. Dieser HTTP Proxy wird in den Proxyeinstellungen des lokalem Webbrowsers eingetragen. War hier zuvor bereits ein Proxy eingetragen, so wird diese vom HTTP Proxy übernommen, so daß die Kommunikation weiter wie gewohnt erfolgt.

Dieser HTTP Proxy ist jedoch nicht nur auf den Webbrowser beschränkt. Werden die Einstellungen in andere proxyfähige Anwendungen eingetragen, so kann diese Kommunikation mit aufgezeichnet werden.

Für .NET Anwendungen ist dies im Regelfall nicht nötig, da diese die Einstellungen des Internet Explorers übernehmen, wenn nicht anders definiert.

Fiddler ist jedoch nicht nur auf lokale HTTP Einstellungen beschränkt. Dies ist nur die Standardeinstellung. Durch eine Option kann dieser Proxy auch vom Netzwerk aus angesprochen werden. Somit ist es dann bspw. möglich Anfragen von Windows Mobile Anwendung mit zu protokollieren.

 

Um die HTTP-Kommunikation vom Windows Mobile Gerät über den Proxy zu aktivieren, muss dieser auch in Windows Mobile eingestellt werden und Fiddler hierzu ausgeführt werden. Wird Fiddler nicht ausgeführt, so kommt es zu Fehlern in Ihrer mobilen Anwendung.
Hierzu aktivieren Sie bitte den Punkt Verbindungen unter Start->Einstellungen auf dem Karteireiter Verbindungen. Wählen Sie dort dann unter dem Punkt Firmennetzwerk den Eintrag Proxyserver einrichten. Ist bereits ein Proxy eingetragen, so wählen Sie stattdessen Proxyserver bearbeiten aus.
Aktivieren Sie dann beide dargestellten Häckchen. Unter Proxyserver tragen Sie die IP-Adresse des Computers ein, auf welchem Fiddler ausgeführt wird (Beispiel: 192.168.0.5).
Wählen Sie danach die Schaltfläche Erweitert... aus. Aktivieren Sie nun im neu erscheinenden Dialog den Eintrag beginnend mit HTTP. Tragen Sie im erscheinenden Dialog im Punkt Anschluss die Portadresse von Fiddler ein. Der Standardwert ist normalerweise 8888.

Wenn Sie dieses Tool installiert haben und es aufrufen, wird normalerweise die HTTP Kommunikation bereits mitprotokolliert. Alternativ können Sie die Protokollierung mittels "F12" aktivieren/deaktivieren.

Rufen Sie in Ihrem Webbrowser die gewünschte ASMX-Seite / ASPX Seite auf, So sehen Sie bei einem Doppelklick auf den entsprechenden Eintrag bereits, ob die Antworten des Webservers komprimiert werden.

(Kommunikation ist nicht komprimiert)

(Kommunikation ist komprimiert)

Darüber hinaus können Sie sich in den entsprechenden Karteireitern die Daten ansehen, welche ausgetauscht werden. Sollten diese komprimiert sein, so kann Fiddler diese auch dekomprimiert darstellen.

Teil 3: Der Client

Der nachfolgend beschriebene Teil basiert auf einem englischsprachigen Artikel der Flow Group, hat aber im Gegensatz dazu einige Vorteile:

  • Anstatt ein Pseudoprotokoll zu verwenden (zHttp), wird hier das reguläre Http Protokoll verwendet. Vorteil hierbei ist, daß in der zur verwendenden Anwendung keine Modifikationen nötig sind und weiterhin das Http Protokoll funktional weiterverwendet werden kann. Es wird lediglich eine Zeile Code in der Anwendung selbst benötigt.
  • Es wurde darauf wert gelegt, daß die Implementation hierbei eher dem Designguide des WebRequest folgt.

Bevor wir jedoch hierzu kommen fangen wir lieber von Vorne an.

Um eine Komprimierung zu ermöglichen benötigt man Klassen oder eine Bibliothek, welche diese Aufgaben übernimmt. Hierfür gibt es lediglich 2 Möglichkeiten: SharpZipLib und zlibCE von OpenNETCF. Welche Bibliothek Sie letztlich verwenden, bleibt Ihnen überlassen.
Ich habe mich für die SharpZipLib Bibliothek entschieden. Dies hat einige Gründe:

  1. zlibCE ist nativ entwickelt worden und bietet zusätzlich einen Wrapper für das .NET Compact Framework, während die SharpZipLib komplett in C# erstellt worden ist. Dabei gilt jedoch zu beachten, daß zlibCE vermutlich schneller ist (Dies werde ich zu einem späteren Zeitpunkt testen).
  2. SharpZipLib ist neuerdings direkt für das .NET Compact Framework vorhanden
  3. zlibCE ist noch ziemlich neu, während SharpZipLib sich bereits bewährt hat.
  4. SharpZipLib unterstützt den Zip- und Deflate-Algorithmus und besitzt dazu noch einige weitere Funktionen. zlibCE unterstützt lediglich den Zip-Algorithmus.

Nachdem nun also bereits eine Komprimierungsbibliothek vorhanden ist, gilt es diese zu implementieren. Wie die Komprimierungsbibliothek für diesen Zweck zu verwenden ist, erfahren Sie im folgenden Abschnitt.

Das folgende Schaubild zeigt die Abhängigkeiten von SoapHttpClientProtocolWebRequest und WebResponse, aus denen u.a. eine WebService-Referenz besteht.

Wie Sie sehen, verwendet die abstrakte Klasse SoapHttpClientProtocol intern die Klassen WebRequest und WebResponse (leider nicht im Schaubild darstellbar).
Da die komprimierten Daten mittels der Methode GetResponseStream() der Klasse WebResponse zurückgegeben werden ist es sinnvoll an dieser Stelle anzusetzen. Somit gilt es also eine Proxyklasse für die Klasse WebResponse zu erstellen und die Methode GetResponseStream() zu überschreiben.
Damit diese Methode jedoch auch den dekomprimierten Stream zurückgibt ist es dementsprechend nötig auch die Klasse WebRequest zu überschreiben. Diese liefert nämlich mittels GetResponse ein Objekt der Instanz WebResponse zurück.

.
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using ICSharpCode.SharpZipLib.GZip;
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;

namespace NetCompressionLibrary
{
    public class CompressedHTTPWebResponse:System.Net.WebResponse
    {
        // Create Proxy object
        private HttpWebResponse response;
        private System.Uri uri;

        internal CompressedHTTPWebResponse(WebRequest request, System.Uri uri)
        {
            this.uri = uri;
            response = (HttpWebResponse)request.GetResponse();
        }
        public override System.IO.Stream GetResponseStream()
        {
            if (response.ContentEncoding == "gzip")
            {
                return new GZipInputStream(response.GetResponseStream());
            }
            else if (response.ContentEncoding == "deflate")
            {
                return new InflaterInputStream(response.GetResponseStream());
            }
            else
            {
                return response.GetResponseStream();
            }
        }
        public override void Close()
        {
            response.Close();
        }

        public override System.Uri ResponseUri
        {
            get
            {
                return uri;
            }
        }
    }
}

Die Klasse CompressedHTTPWebResponse leitet somit von der abstrakten Klasse WebResponse ab.

Sie erhält zusätzlich eine Variable vom Typ HttpWebResponse, da unsere Klasse als eine Schale hierfür dienen soll. HttpWebRequest ist hierbei der Handler für HTTP Anfragen aus dem .NET (Compact) Framework heraus.

Wir wollen ja eigentlich auch nur die Methode GetResponseStream() überschreiben. Intern wird jedoch alles weitere auf die intern verwendete Variable response vom Typ HttpWebResponse weitergeleitet.

Damit in der überschriebenen Methode auch die Komprimierung verwendet werden kann, muss dem Projekt die Assembly ICSharpCode.SharpZipLib.dll hinzugefügt werden. Sie finden diese im heruntergeladenen Archiv von SharpZipLib im Ordner "SharpZipLib_0852_BinDoc\current\netcf-20".

Zusätzlich benötigen sie die beiden using Statements using ICSharpCode.SharpZipLib.GZip; und using ICSharpCode.SharpZipLib.Zip.Compression.Streams; , damit Sie die Klassen zur Komprimierung einfacher in Ihrer Klasse verwenden können.

Bevor Sie die Dekomprimierung verwenden, prüfen Sie auf das ContentEncoding des verwendeten Objektes response. Hier ist die Information enthalten, ob die erhaltenen Daten komprimiert sind, respektive, wie diese komprimiert wurden. Wird keine Komprimierung verwendet, so wird der ResponseStream von response einfach 1:1 zurückgegeben und ermöglicht so die Klasse als Standardklasse für HTTP-Kommunikation anstatt HttpWebRequest zu verwenden.
Wird die GZip-Komprimierung durch den Webserver verwendet (ContentEncoding == "gzip"), so wird um den ResponseStream noch der GZipInputStream gelegt, welcher die Daten beim Abfragen direkt dekomprimiert. Analog geschieht dies beim Deflate-Algorithmus (ContentEncoding == "deflate") mit dem InflaterInputStream.

Wie bereits beschrieben ist für die korrekte Verwendung von CompressedHTTPWebResponse auch analog eine Ableitung der Klasse WebRequest nötig.

.
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;

namespace NetCompressionLibrary
{

    public class CompressedHTTPWebRequest : System.Net.WebRequest
    {
        private HttpWebRequest request;
        private System.Uri uri;

        private CompressedHTTPWebRequest(System.Uri uri)
        {
            this.uri = uri;
            request = (HttpWebRequest)WebRequest.Create(uri);
            request.Headers.Add("Accept-Encoding", "gzip, deflate");
        }
        
        public override System.Net.WebResponse GetResponse()
        {
            CompressedHTTPWebResponse response = new CompressedHTTPWebResponse(request,uri);
            return (WebResponse)response;
        }
        ...

        /// <summary>
        /// Creates a CompressedWebRequest object for doing compressed HTTP Communication
        /// </summary>
        /// <param name="uri">The URI of the WebService</param>
        /// <returns></returns>
        public static CompressedHTTPWebRequest Create(Uri uri)
        {
            return new CompressedHTTPWebRequest(uri);
        }
    }
}

Hier sehen Sie, daß analog zu CompressedHTTPWebResponse auch diese Klasse eine Schale (Proxyklasse) für HttpWebRequest darstellt. Hier wird daher ebenfalls ein Objekt vom Typ HttpWebRequest erstellt, an welches alle Anfragen weitergeleitet werden (die hier dargestellte Klasse ist lediglich die Minimalimplementation. Das im Anhang beigefügte Archiv ist eine Vollimplementation).

Damit man also komprimierte Daten anfordern kann ist es nötig dem verwendeten HttpWebRequest einen Header beizufügen, der dem Webserver gegenüber erklärt, daß die Komprimierung unterstützt wird.

Um jedoch auch die CompressedHTTPWebResponse zu erhalten, ist es nötig die Methode GetResponse() zu überschreiben.

Die statische Methode Create erzeugt konform zum WebRequest jeweils ein Objekt vom Typ CompressedHTTPWebRequest und gibt diesen zurück.

Mit diesen beiden Klassen ist es bereits möglich Daten mittels HTTP Kommunikation auszutauschen. Das folgende Beispiel zeigt, wie dies geht.

Teil 3.1: Abfragen komprimierter Daten mittels CompressedHTTPWebRequest

Versuchen Sie es doch nun einmal, mit diesen neuen Klassen eine Verbindung mit bspw. der URL http://msdn.microsoft.com.
.
            ...
            CompressedHTTPWebRequest wr = CompressedHTTPWebRequest.Create(http://msdn.microsoft.com);
            StreamReader sr = new StreamReader(wr.GetResponse().GetResponseStream());
            MessageBox.Show(sr.ReadToEnd());
            ...

Wenn Sie die Methode CompressedHTTPWebResponse debuggen, werden Sie sehen, daß die Seite mit komprimierten Daten geantwortet hat.

Was noch als letztes fehlt ist die Verwendung dieser Klassen innerhalb der WebService-Referenz.

Teil 3.2: komprimierte Datenkommunikation mit WebServices

Wie ist es nun aber möglich WebService-Referenz, bzw. der Klasse SoapHttpClientProtocol beizubringen, die neuen Klassen CompressedHTTPWebRequest und CompressedHTTPWebResponse intern zu verwenden. Sie leiten ja von WebRequest und WebResponse ab. Also sollte dies möglich sein.

Nun könnte man ja auf die Idee kommen und die Klasse SoapHttpClientProtocol zu überschreiben. Dies wäre jedoch viel zu aufwändig und ist auch gar nicht nötig.

Viel sinnvoller wäre es doch, genauso wie bereits beim HTTP-Handler auf der Serverseite den HTTP-Handler für die komprimierten Daten auf der Clientseite zu verwenden. Hierzu müsste lediglich der Standardhandler für HTTP deregistriert und unser Handler registriert werden.

Dies geschieht mittels der Codezeile CompressedHttpProtocol.Register();.Dies ist die einzige Zeile (ich sprach bereits am Anfang des Artikels davon), welcher der Clientanwendung hinzugefügt werden muss. Hierdurch wird der "neue" HTTP-Handler registriert und wird für die Laufzeit der Anwendung verwendet.

Einziges Problem hierbei ist, daß dieser Handler sich nicht deregistrieren lässt. Dies ist jedoch auch nicht nötig, da unser Handler ebenfalls unkomprimierte Daten verarbeiten kann.

Achtung: Es gilt zu beachten, daß die eben beschriebene Codezeile VOR der Verwendung eines WebServices aufgerufen wird.

Hinter dieser Codezeile verstecken sich 2 kleine Klassen.

.
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;

namespace NetCompressionLibrary
{
    public class CompressedHttpProtocol
    {
        /// <summary>
        /// Register the protocol
        /// </summary>
        /// <returns></returns>
        static public bool Register()
        {
            return WebRequest.RegisterPrefix("http", new CompressedHTTPWebRequestCreate());
        }
    }
}

Bei dieser Klasse handelt es sich um eine kleine Hilfsklasse. Die Methode Register() registriert den CompressedHTTPWebRequest mit einer weiteren Hilfsmethode, welche im folgenden beschrieben wird, als Handler für die HTTP Kommunikation. Alle Anfragen, welche das Prefix "http" verwenden, werden also durch unsere neuen Klassen verarbeitet. Dies ist generell sinnvoll, da, wie bereits beschrieben, auch unkomprimierte HTTP Kommunikation verarbeiten können.

Die Hilfsklasse CompressedHTTPWebRequestCreate sieht, wie folgt aus:

.

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;

namespace NetCompressionLibrary
{
    public class CompressedHTTPWebRequestCreate : IWebRequestCreate
    {
        /// <summary>
        /// Create the WebRequest object able to handle the Uri
        /// </summary>
        /// <param name="uri">the requested Uri</param>
        /// <returns>the WebRequest object</returns>
        public System.Net.WebRequest Create(System.Uri uri)
        {
            return CompressedHTTPWebRequest.Create(uri);
        }
    }
}

Diese Klasse leitet vom Interface IWebRequestCreate ab, welches für die Registrierung eines Handlers benötigt wird und beim Aufruf jeweils die korrekten WebRequest und WebResponse Klassen verwendet.

Wenn Sie nun, wie gewohnt Ihren Webverweis und die eben erstellte Bibliothek Ihrem Projekt hinzufügen und den clientseitigen HTTP-Handler wie eben gezeigt registrieren, können Sie wie gewohnt Ihre Anwendungen weiter entwickeln und zusätzlich Zeit Platz und Geld sparen.

Fazit

Eigentlich nicht viel Aufwand, jedoch eine Menge "Benefit". Microsoft, bitte baut dies doch direkt in das .NET Compact Framework 3.5 ein. Ihr erspart vielen Personen eine Menge Ärger.

Die Bibliothek lässt sich natürlich noch erweitern. So liesse sich, mit entsprechend erstellten Bibliotheken die Komprimierung auch noch verschlüsseln. Dies könnte ebenfalls mit einem HTTP-Händler durchgeführt werden. Hiermit wäre das einfache Abhören der Kommunikation zuerst einmal unterbunden.

 

Link: Bibliothek als Source und Binary NetCompressionLibrary.zip (226,15 KB)

 

This posting is provided "AS IS" with no warranties, and confers no rights.

Thursday, July 05, 2007 11:29:03 AM (W. Europe Standard Time, UTC+01:00)  #    Comments [0]   .NET Compact Framework | Windows Mobile  |  Trackback
All comments require the approval of the site owner before being displayed.
Name
E-mail
(will show your gravatar icon)
Home page

Comment (Some html is allowed: a@href@title, blockquote@cite, em, strike, strong, sub, sup, u) where the @ means "attribute." For example, you can use <a href="" title=""> or <blockquote cite="Scott">.  

Enter the code shown (prevents robots):

Live Comment Preview
Copyright © 2008 Peter Nowak. All rights reserved.
DasBlog 'Portal' theme by Johnny Hughes.