Rijden op het internet Bandwagon




Het verzenden van grote pagina's van HTML is niet langer een probleem nu dat we in staat zijn om gecomprimeerde pagina's te sturen!

Na twee weken van non-stop programmering, de webtoepassing gereed en getest. Alles is A-OK en de glimlach op de gezichten van uw klanten zullen zich herinneren in een vreemde manier van 'Jaws'. Behalve voor een ding. Iemand in de rug schuchter gevraagd of er iets gedaan kon worden om de snelheid van de pagina met zoekresultaten die zo veel tekst bevat. Op dat moment weet je dat je een volledige kopie van de aanvraag met u had moeten brengen, in plaats van boven de lijn te tonen 33.6kb modem te werken.



Maar niet alles is verloren. Er zijn manieren om de hoeveelheid gegevens die naar de client moeten worden gericht te verminderen, en ik heb het niet tegen minder informatie te verzenden, maar eerder om gecomprimeerde gegevens te verzenden. Klinkt interessant? Lees verder en leer.

AssumptionsSince frivole Dit artikel beschrijft de mogelijkheden en technieken die zal toevoegen aan de complexiteit van een webapplicatie, wordt ervan uitgegaan dat u al weet hoe u een web applicatie, in het bijzonder, een ISAPI DLL te creëren, en als zodanig de toepassing werken. Als zodanig ik een aantal details over te slaan, maar ik verzeker u - ik zal met alle opties en de code die specifiek nodig zijn voor de technieken die we hier toepassen staan.

Met dit in het achterhoofd, gaan we een beetje meer 'sap uit uw good ol' knijp internet lijn.

Hoe bestaat het magie? Hoe is het mogelijk dat u misschien vragen? Je hebt waarschijnlijk op een of ander moment gedownload een gecomprimeerd bestand alleen om te ontdekken dat uw browser of andere manier geïnterpreteerd de gegevens als ofwel een webpagina of tekst en toon deze op het scherm in al zijn glorie. Het is geen mooi plaatje op zijn zachtst gezegd. Als je om de gegevens te comprimeren voordat deze naar de klant, lijkt niet zo vreemd dan? Niet echt, maar zorg ervoor dat de klant weet dat hij te beheren op een andere manier.

Het geheim is verborgen in de gegevens van de klant stuurt naar de webserver en op de gegevens van de webserver reageert met. Het heet inhoud codering. In het kort, is het mogelijk om de gegevens te coderen levert toepassingen voor de klant, en de enige voorzorgsmaatregel nemen is om ervoor te zorgen dat de cliënt weet hoe hij de data-encoding formaat gekozen verwerken. Dit op zijn beurt is eenvoudig, omdat de klant vertelt u welke formats het aankan wanneer u het verzoek naar de server te sturen.

Dus het komt er eigenlijk op neer dat je nodig hebt om de volgende stappen te nemen als je wilt coderen de gegevens teruggegeven aan de klant:

  1. Controleer of de klant in staat is om het type codering dat u wilt gebruiken te behandelen
  2. Codeert de data in de gewenste formaat
  3. Return nieuwe gecodeerde gegevens en vertel de klant welk formaat je gecodeerd in
  4. Welk formaat moet ik gebruiken? Wij zijn geïnteresseerd in het comprimeren van de data terug naar de client. Er is een soort specifiek coderen voor dit doel, en de naam "leeggelopen". De compressie-algoritme dat wordt gebruikt in het type codering correspondeert met het leeglopen algoritme dat de zlib compressie bibliotheek implementeert. U kunt hier meer informatie over deze bibliotheek lezen: http://www.cdrom.com/pub/infozip/zlib of kijk op de RFC beschrijft het algoritme en binair formaat hier: http://www.funet.fi/ pub/doc /rfc/rfc1950.txt.

    Hoewel je zou denken dat je al de bestanden die nodig zijn om de zlib compressie bibliotheek te gebruiken - doe je niet! Althans niet precies. Hoewel de installatie-cd van Delphi wordt geleverd met een kopie van de zlib compressie bibliotheek, in de vorm van vooraf gecompileerde object-bestanden en een aantal bestanden te importeren, het verbergen van de details die we moeten gebruiken. Meer daarover later, maar voor nu laten s volstaat te zeggen dat we een betere interface nodig voor de bibliotheek en om deze reden heb ik gekozen om mijn eenheid import Zlib en een link naar de vooraf gecompileerde dll downloaden geven: http: // www. winimage.com/zLibDll/.

    Met betrekking tot het 'leeglopen' soort codering wordt alleen Microsoft Internet Explorer te hanteren en pas weer latere versies (versie 4 en hoger handgrepen falen, iets minder dan dat is niet veilig). Dit is niet een big deal omdat de andere browsers, zoals Netscape, niet zeggen dat ze in staat zijn om de aard van compressie codering af te handelen. In dit geval onze webtoepassing gewoon niet terug met de gecomprimeerde gegevens. Het enige verschil zou een beetje 'meer tijd om de gegevens te downloaden naar de client te zijn. Dit is niet erger dan wat we nu hebben, dus ik denk dat we mee leven.

    Ok, ik heb het bestand, wat nu? Nu is het tijd om aan de slag om de bloederige details. Laten we uitgaan van een goede start met de oprichting van een nieuw project in Delphi 5 ISAPI en zien waar het ons. Je moet de drive om te importeren gedownloade voegen bij dit project ook. De dll kan worden gedownload zodra deze wordt in de map C: \ WINNT \ System32 (of de overeenkomstige directory) of in dezelfde map als een webapplicatie.

    Na het aanmaken van het nieuwe project, voeg wat actie om het, letterlijk. Voeg een actie om het webformulier en maak een leeg event handler voor. Maak de actie van de standaard actie, en aangezien dit is slechts een demo applicatie om onze nieuwe manier van terugkerende gegevens proberen.

    Nu hebben we een event handler aan een lege actie om te vertrekken? S voeg wat code om het te laten doen wat wij nodig hebben. Ik zal je de volledige event handler en dan ga ik door de details.

    procedure TWebModule1.WebModule1WebActionItem1Action (Sender: TObject; Request: TWebRequest; Antwoord: TWebResponse; var
    behandeld: Boolean);
    var
    PlaintextStream: Tstream;
    CompressedStream: Tstream;
    beginnen
    indien (ClientAcceptsDeflate (Request)) en dan
    beginnen
    // 1 Maak eerst een tijdelijke stroom met de gegevens die moeten worden geretourneerd
    PlaintextStream: = TStringStream.Create ('Deze tekst is gecomprimeerd');
    proberen
    // 2 Ten tweede creëren tijdelijke stroom voor onze gecomprimeerde gegevens
    CompressedStream: = TMemoryStream.Create;
    proberen
    // 3 Nu comprimeren de stroom ...
    zLibCompressStream (PlaintextStream, CompressedStream);

    // ... Het keert
    CompressedStream.Position: = 0;
    Response.ContentStream: = CompressedStream;
    behalve
    FreeAndNil (CompressedStream);
    lift;
    end; Probeer // uitzondering - te vermijden memory leaks
    eindelijk
    // 4 Tenslotte herschikken tijdelijk object
    FreeAndNil (PlaintextStream);
    end; Probeer // eindelijk - te vernietigen object stroming in duidelijke tekst
    Response.ContentType: 'text/plain' =;
    Response.ContentEncoding: = 'leeglopen';
    Response.StatusCode: = 200;
    behandeld: = True;
    end // gegevens, indien de klant accepteert gecomprimeerde
    anders beginnen
    Response.Content: = 'Niet-gecomprimeerd';
    Response.ContentType: 'text/plain' =;
    Response.StatusCode: = 200;
    behandeld: = True;
    end; // Indien de opdrachtgever niet gecomprimeerde data accepteren
    end; Procedure // TWebModule1.WebModule1ActionItem1Action

    Het if-statement prime hier bepaalt of de klant gecomprimeerde data kan verwerken en stuurt zowel de data gecomprimeerd of ongecomprimeerd naar de opdrachtgever daarvan. De niet-gecomprimeerde gegevens worden behandeld als je altijd in geslaagd gegevens in een web-applicatie, zodat je niet verder te bespreken. In plaats daarvan gaan we focussen op als-dan een deel van de verklaring, indien-dat gecomprimeerde data omgaat. Je waarschijnlijk al gemerkt dat we met behulp van twee nieuwe procedures/functies hier, namelijk ClientAcceptsDeflate en zLibCompressStream. Ik ga door die verderop in dit artikel.

    Aannemende dat we een procedure die een stroom vereist als invoer hebben gekregen, comprimeert de gegevens van deze stroom houdt en schrijft de gecomprimeerde gegevens in een uitvoerstroom, kunnen we de bovenstaande aldus code beschrijven:

    1. Maak eerst een tijdelijke stroom die alles wat we willen terugkeren naar de client
    2. Tweede comprimeren gegevens en zet de gecomprimeerde data in een nieuwe stroom
    3. Deze nieuwe stroming, het houden van onze gecomprimeerde data, we gewoon terug naar de client
    4. Tot slot ruimen onze tijdelijke objecten
    5. U kunt de desbetreffende punten van deze lijst in de commentaren genummerde event handler boven te vinden. Het is de code vrij eenvoudig, en moet ook zijn omdat we verborg de bloederige details in twee functies, die we later zullen bespreken.

      Een ding om op te merken is dat als je eenmaal de eigenschap van het object Response toewijzen aan onze ContentStream reactie stroom-bject neemt eigenaarschap van de stroom. Zodra de reactie van gegevens naar de klant stroom wordt gestuurd zal worden vrijgegeven aan ons, dus we moeten ervoor zorgen dat u niet per ongeluk zelf weet te bevrijden. In het geval van een uitzondering, maar ik stelde voor dat de baan van slag is gegaan, en bevrijd dan de stroom voor het uitdragen van de uitzondering in plaats van de top.

      Parlez-vous français? Om te bepalen of de cliënt weet hoe te handelen gecomprimeerde data moeten kijken naar de gegevens die ons stuurt in de eerste plaats. Een typische web verzoek ziet er als volgt uit (verzoek vervalsing, dan is de informatie misschien niet 100% correct):

      Index.html HTTP GET/1,0
      Accept-Types: */*
      Accept-Encoding: gzip, leeglopen
      User-Agent: Mozilla 4.0 (Microsoft Internet Explorer 5.0 compatibel, NT)

      Wat ons interesseert is de lijn die gaat Accept-Encoding: gzip, leeglopen. Vertelt ons wat soorten die coderen voor de cliënt in staat is om te accepteren, en in dit geval de gegevens die is gecodeerd in de gzip-formaat, evenals de indeling van leeglopen kan accepteren. Dat laatste is wat we nodig hebben, laten we eens kijken hoe je die kennis binnen onze webapplicatie krijgen. De functie is vergelijkbaar met het volgende:

      We moeten schrijven de functie ziet er als volgt uit:

      functie ClientAcceptsDeflate (const Vraag: TWebRequest): Boolean;
      var
      EncodingTypes: koord;
      beginnen
      // Inpakken en opnieuw formatteren van de lijst van soorten codering op aanvraag
      EncodingTypes: = Request.GetFieldByName ('HTTP_ACCEPT_ENCODING');
      EncodingTypes: = UpperCase (StringReplace (EncodingTypes, ',', '/', [rfReplaceAll]));
      EncodingTypes: = '/' + StringReplace (EncodingTypes, '', '', [rfReplaceAll]) + '/';

      // Geeft de vlag
      Resultaat: = (Pos ('/ DEFLATE /', EncodingTypes)> 0);
      end; // Functie ClientAcceptsDeflate

      Kortom, ik moet de waarden opnieuw formatteren gzip, leeglopen / GZIP/DEFLATE / en dan controleren of de string / DEFLATE / is de binnenkant van het. Als u geïnteresseerd bent om te weten wat andere gebieden zijn te vinden in het verzoek zijn, dan adviseer ik je een kijkje nemen op http://msdn.microsoft.com/library/psdk/iisref/isre504l.htm nemen en maakt gebruik van de variabele naar ALL_HTTP controleren variabelen zoals de klant daadwerkelijk stuurt.

      Naturellement, parlons! Daarna hebben we vastgesteld dat de klant gecomprimeerde data aankunnen alles wat we hebben verlaten om te doen is het daadwerkelijk produceren van gecomprimeerde data en dit is waar de magie komt.

      Zoals eerder gezegd, zullen we de zlib compressie bibliotheek te gebruiken om de compressie werkelijkheid doen. De code bestaat uit de volgende stappen:

      1. Stel buffer voor de gegevens naar de motor en de gecomprimeerde data van accepteren
      2. Initialiseren van de compressie-engine
      3. Voer de platte tekst gegevens in de input buffer van de input stream
      4. Comprimeer de invoerbuffer aan de uitgangsbuffer
      5. Noteer de gegevens van de uitgangsbuffer de output stream
      6. Herhaal de stappen 3-5 totdat je hebt geleegd meer gegevens in de input stroom en buffers
      7. Sluiten compressie motor
      8. Laten we graven in de details en zien wat we te maken hebben met:

        procedure zLibCompressStream (const Bron, Bestemming: Tstream);
        var
        z_s: z_stream;
        rc: Integer;
        // 1 Buffers voor invoer en uitvoer
        SourceBuffer: serie [0..BufferSize-1] van Byte;
        DestinationBuffer: serie [0..BufferSize-1] van Byte;
        beginnen
        // 2 Bereid de dataset zlib
        z_init_zstream (z_s);
        z_s.next_in: = SourceBuffer;
        z_s.next_out: = DestinationBuffer;
        z_s.avail_out: = buffersize;

        // 2 Initialiseer de compressie-engine
        deflateInit2 (z_s, Z_BEST_COMPRESSION, Z_DEFLATED, -15, 9, Z_DEFAULT_STRATEGY);

        // Nu comprimeren de stroom
        proberen
        herhaling
        // 3 zie als we om meer gegevens te voeden om de compressie motor
        indien (z_s.avail_in = 0) en (Source.Position en dan
        beginnen
        z_s.next_in: = SourceBuffer;
        z_s.avail_in: = Source.Read (SourceBuffer, omvang buffer);
        end; // Als de invoergegevens volledig is uitgeput

        // 4 comprimeren data
        indien (z_s.avail_in = 0) en dan
        rc: = leeglopen (z_s, Z_FINISH)
        andere
        rc: = leeglopen (z_s, Z_STREAM_END);

        // 5 Controleer of er gegevens worden geschreven naar de bestemming gecomprimeerde
        indien (z_s.avail_out = 0) of (rc = Z_STREAM_END) en dan
        beginnen
        Destination.WriteBuffer (DestinationBuffer, buffersize - z_s.avail_out);
        z_s.avail_out: = buffersize;
        z_s.next_out: = DestinationBuffer;
        end; // Als de gegevens beschikbaar zijn voor het schrijven kreeg

        // 6 Herhaal totdat alle buffer
        tot (rc Z_OK) of ((rc = Z_STREAM_END) en (z_s.avail_out buffersize =) en (z_s.avail_in = 0));
        eindelijk
        // 7 Clean up van de gegevens motor
        deflateEnd (z_s);
        end; Probeer // eindelijk - na schone motor
        end; Procedure // zLibCompressStream

        Zoals eerder is het mogelijk om de stappen te combineren om de lijst met bovenstaande opmerkingen genummerd. De reden waarom we niet de zlib code die zou kunnen gebruiken? S opgenomen in Delphi is dat het verbergt de routine deflateInit2 en de parameters die nodig zijn bij de uitvoering van een deel van de groep om niet alle benodigde code bloot.

        Om gecomprimeerde gegevens, zodat de browser kan omgaan produceren, moeten we data te comprimeren zonder beginopname. De header record is een klein overzicht van de informatie die is geschreven aan het begin van de gecomprimeerde gegevens, en helpt de decompressie motor weten hoeveel data die volgen. We kunnen ervoor kiezen om dit niet te beginopname schrijven door het passeren van een negatieve waarde voor de parameter wBitSize de procedure deflateInit2. Aangezien de standaard leeglopen de browser zich te houden, verwacht geen of weten hoe ze deze header te behandelen, moeten we uit te filteren. Omdat we niet konden deflateInit2 rechtstreeks met de met Delphi bijgeleverde zlib code noemen we moesten hun toevlucht nemen tot een kopie van de dll volledige compressie bibliotheek.

        Het compressiemotor kan de data uit de ingangsbuffer comprimeren en schrijven naar de uitgangsbuffer. Als de output buffer vol is, ze moeten onze code de buffer spoelen wegschrijven deze naar de bestemming, in ons geval een stroom. Wanneer het in staat is om alle gegevens van de invoer buffer te comprimeren, onze code nodig heeft om de buffer weer te vullen met zoveel mogelijk gegevens. De compressie-engine zorgt voor de rest.

        Test itAfter uw web applicatie te compileren (zie onderaan artikel voor een kopie van het voorbeeldproject in dit artikel toegepast), moet je idealiter probeer het met zowel een browser die gecomprimeerde gegevens omgaat, en een die dat niet doet. U kunt Internet Explorer 5.4 en Netscape 4.6 gebruiken als de eerste als de laatste. De browser die zorgt voor de compressie moet de tekst laten zien "Deze tekst wordt gecomprimeerd 'en de andere' ongecomprimeerde 'voor verificatie.

        Gemiddelde compressieverhouding op tekstuele inhoud is ongeveer 5-6 keer (15-20% van de oorspronkelijke grootte), dan is het effect moet duidelijk zichtbaar zijn op grote webpagina's.

        Verpakken Upwell, dat is alles. Met de code en de kennis die in dit artikel moet je nu in staat om te gaan met de gecomprimeerde gegevens van uw webapplicatie. Hoewel we een ISAPI DLL in dit artikel hebt gemaakt, moet de theorie en de code hetzelfde voor de NSAPI en CGI-toepassingen blijven.

        Ik heb de vrijheid genomen om een ​​eenheid met de twee hierboven beschreven functies, evenals een kopie van het voorbeeld in dit artikel te maken. U kunt de bestanden te downloaden uit de onderstaande selectie. Als er suggesties of dingen die je wilt reageren kan worden bereikt op lasse@cintra.no.

        Bestand om te downloaden:

        • zlib dll (van de auteurs website)
        • Unit import zlib.dll
        • Voorbeeld van een project (met inbegrip van eenheden met de twee functies en de eenheid van de invoer)
        • Alleen de eenheid met de twee functies die we schreven

        Er zijn een paar van de afwerking noten in gedachten te houden:

        • De compressie motor niet vast te stellen of de data leent zich gemakkelijk tot compressie of niet voordat ze beginnen te kauwen. Dit betekent dat u de gegevens kunt voeren via het dat niet kan worden samengedrukt en kan ook toenemen in omvang plaats. Voor tekst en webpagina's is geen probleem toch, maar ik zou graag een aantal testen doen voordat het leveren van het in JPEG of GIF-formaat.
        • De compressie wordt gedaan op de server voordat ze worden verzonden, dus als de klant probeert een grote webpagina te downloaden dan is de webapplicatie laadt in wezen de hele pagina in het geheugen, comprimeert het en stuurt het. Als het geheugengebruik op de server een probleem is, dan zou ik de uitvoering van de compressie-code in een klasse afgeleid van Tstream suggereren dat comprimeert als je leest vanuit het. Zo wordt de compressie uitgevoerd on-the-fly, als de gegevens worden verzonden en kan direct worden gevoed vanaf de schijf door de compressie bibliotheek om de klant. Klassen om dit te doen zijn beschikbaar vanaf de homepage van het pakket genaamd StreamFilter.



Verlaat een commentaren