Megosztás:


Adattömbcsatorna

A ChunkingChannel minta bemutatja, hogyan használható egy egyéni protokoll vagy rétegzett csatorna az tetszőlegesen nagy méretű üzenetek darabolására és törlésére.

Ha nagy üzeneteket küld a Windows Communication Foundation (WCF) használatával, gyakran célszerű korlátozni az üzenetek puffereléséhez használt memória mennyiségét. Az egyik lehetséges megoldás az üzenet törzsének streamelése (feltéve, hogy az adatok nagy része a törzsben található). Egyes protokollok azonban a teljes üzenet pufferelését igénylik. A megbízható üzenetkezelés és a biztonság két ilyen példa. Egy másik lehetséges megoldás, ha a nagy üzenetet kisebb, adattömböknek nevezett üzenetekre osztja fel, egyenként elküldi ezeket az adattömböket, és újrakonfigurálja a nagy üzenetet a fogadó oldalon. Maga az alkalmazás is elvégezheti ezt az adattömb-készítést és -bontást, vagy használhat egy egyéni csatornát.

Az adattömb-készítést mindig csak a teljes elküldendő üzenet létrehozása után szabad alkalmazni. Az adattömbcsatornát mindig egy biztonsági csatorna és egy megbízható munkamenet-csatorna alá kell rétegíteni.

Feljegyzés

A minta telepítési eljárása és összeállítási utasításai a témakör végén találhatók.

Adattömbcsatorna feltételezései és korlátozásai

Üzenetstruktúra

Az adattömbcsatorna a következő üzenetstruktúrát feltételezi az üzenetek darabolásához:

<soap:Envelope>
  <!-- headers -->
  <soap:Body>
    <operationElement>
      <paramElement>data to be chunked</paramElement>
    </operationElement>
  </soap:Body>
</soap:Envelope>

A ServiceModel használatakor az 1 bemeneti paraméterrel rendelkező szerződésműveletek megfelelnek ennek az üzenetformának a bemeneti üzenethez. Hasonlóképpen, az 1 kimeneti paraméterrel vagy visszatérési értékkel rendelkező szerződésműveletek megfelelnek ennek az üzenetformának a kimeneti üzenethez. Az alábbi példák az ilyen műveletekre mutatnak be példákat:

[ServiceContract]
interface ITestService
{
    [OperationContract]
    Stream EchoStream(Stream stream);

    [OperationContract]
    Stream DownloadStream();

    [OperationContract(IsOneWay = true)]
    void UploadStream(Stream stream);
}

Előadások

Az adattömbcsatorna megköveteli, hogy az üzenetek pontosan egyszer legyenek kézbesítve, az üzenetek (adattömbök) rendezett kézbesítése érdekében. Ez azt jelenti, hogy a mögöttes csatornaveremnek munkamenet-alapúnak kell lennie. A munkameneteket az átvitel (például TCP-átvitel) vagy egy munkamenet-alapú protokollcsatorna (például ReliableSession csatorna) biztosíthatja.

Aszinkron küldés és fogadás

Az aszinkron küldési és fogadási metódusok nincsenek implementálva az adattömbcsatorna-minta ezen verziójában.

Adattömb-készítési protokoll

Az adattömbcsatorna meghatároz egy protokollt, amely egy adattömbsorozat kezdetét és végét, valamint az egyes adattömbök sorszámát jelzi. Az alábbi három példaüzenet az indítási, adattömb- és záróüzeneteket mutatja be, amelyek az egyes üzenetek főbb jellemzőit leíró megjegyzésekkel mutatják be.

Üzenet indítása

<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing"
            xmlns:s="http://www.w3.org/2003/05/soap-envelope">
  <s:Header>
<!--Original message action is replaced with a chunking-specific action. -->
    <a:Action s:mustUnderstand="1">http://samples.microsoft.com/chunkingAction</a:Action>
<!--
Original message is assigned a unique id that is transmitted
in a MessageId header. Note that this is different from the WS-Addressing MessageId header.
-->
    <MessageId s:mustUnderstand="1" xmlns="http://samples.microsoft.com/chunking">
53f183ee-04aa-44a0-b8d3-e45224563109
</MessageId>
<!--
ChunkingStart header signals the start of a chunked message.
-->
    <ChunkingStart s:mustUnderstand="1" i:nil="true" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://samples.microsoft.com/chunking" />
<!--
Original message action is transmitted in OriginalAction.
This is required to re-create the original message on the other side.
-->
    <OriginalAction xmlns="http://samples.microsoft.com/chunking">
http://tempuri.org/ITestService/EchoStream
    </OriginalAction>
   <!--
    All original message headers are included here.
   -->
  </s:Header>
  <s:Body>
<!--
Chunking assumes this structure of Body content:
<element>
  <childelement>large data to be chunked<childelement>
</element>
The start message contains just <element> and <childelement> without
the data to be chunked.
-->
    <EchoStream xmlns="http://tempuri.org/">
      <stream />
    </EchoStream>
  </s:Body>
</s:Envelope>

Adattömb üzenete

<s:Envelope
  xmlns:a="http://www.w3.org/2005/08/addressing"
  xmlns:s="http://www.w3.org/2003/05/soap-envelope">
  <s:Header>
   <!--
    All chunking protocol messages have this action.
   -->
    <a:Action s:mustUnderstand="1">
      http://samples.microsoft.com/chunkingAction
    </a:Action>
<!--
Same as MessageId in the start message. The GUID indicates which original message this chunk belongs to.
-->
    <MessageId s:mustUnderstand="1"
               xmlns="http://samples.microsoft.com/chunking">
      53f183ee-04aa-44a0-b8d3-e45224563109
    </MessageId>
<!--
The sequence number of the chunk.
This number restarts at 1 with each new sequence of chunks.
-->
    <ChunkNumber s:mustUnderstand="1"
                 xmlns="http://samples.microsoft.com/chunking">
      1096
    </ChunkNumber>
  </s:Header>
  <s:Body>
<!--
The chunked data is wrapped in a chunk element.
The encoding of this data (and the entire message)
depends on the encoder used. The chunking channel does not mandate an encoding.
-->
    <chunk xmlns="http://samples.microsoft.com/chunking">
kfSr2QcBlkHTvQ==
    </chunk>
  </s:Body>
</s:Envelope>

Záró üzenet

<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing"
            xmlns:s="http://www.w3.org/2003/05/soap-envelope">
  <s:Header>
    <a:Action s:mustUnderstand="1">
      http://samples.microsoft.com/chunkingAction
    </a:Action>
<!--
Same as MessageId in the start message. The GUID indicates which original message this chunk belongs to.
-->
    <MessageId s:mustUnderstand="1"
               xmlns="http://samples.microsoft.com/chunking">
      53f183ee-04aa-44a0-b8d3-e45224563109
    </MessageId>
<!--
ChunkingEnd header signals the end of a chunk sequence.
-->
    <ChunkingEnd s:mustUnderstand="1" i:nil="true"
                 xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
                 xmlns="http://samples.microsoft.com/chunking" />
<!--
ChunkingEnd messages have a sequence number.
-->
    <ChunkNumber s:mustUnderstand="1"
                 xmlns="http://samples.microsoft.com/chunking">
      79
    </ChunkNumber>
  </s:Header>
  <s:Body>
<!--
The ChunkingEnd message has the same <element><childelement> structure
as the ChunkingStart message.
-->
    <EchoStream xmlns="http://tempuri.org/">
      <stream />
    </EchoStream>
  </s:Body>
</s:Envelope>

Adattömbcsatorna architektúrája

Az adattömbcsatorna egy IDuplexSessionChannel olyan csatorna, amely magas szinten követi a tipikus csatornaarchitektúrát. Van egy ChunkingBindingElement , amely képes felépíteni egy ChunkingChannelFactory és egy ChunkingChannelListener. A ChunkingChannelFactory rendszer létrehozza azokat a ChunkingChannel példányokat, amikor a rendszer kéri. A ChunkingChannelListener rendszer létrehozza azokat a ChunkingChannel példányokat, amikor egy új belső csatornát fogadnak el. Maga ChunkingChannel a felelős az üzenetek küldéséért és fogadásáért.

A következő szinten több ChunkingChannel összetevőre támaszkodik az adattömb-protokoll implementálásához. A küldési oldalon a csatorna egy egyéni XmlDictionaryWriter , úgynevezett nevet ChunkingWriter használ, amely elvégzi a tényleges adattömb-készítést. ChunkingWriter a belső csatornát használja az adattömbök küldéséhez. XmlDictionaryWriter Egyéni használatával adattömböket küldhetünk ki, mivel az eredeti üzenet nagy törzse meg van írva. Ez azt jelenti, hogy nem puffereljük a teljes eredeti üzenetet.

Ábra az adattömbcsatorna küldési architektúrájáról.

A fogadó oldalon lekéri az üzeneteket a belső csatornáról, ChunkingChannel és átadja azokat egy egyéni nevűnek XmlDictionaryReaderChunkingReader, amely újrakonfigurálja az eredeti üzenetet a bejövő adattömbökből. ChunkingChannelezt ChunkingReader egy meghívott Message egyéni ChunkingMessage implementációba csomagolja, és visszaadja ezt az üzenetet a fenti rétegnek. Ez a ChunkingReader kombináció lehetővé ChunkingMessage teszi, hogy az eredeti üzenettörzset bontsuk fel, mivel a fenti réteg felolvassa ahelyett, hogy a teljes eredeti üzenettörzset puffereljük. ChunkingReader van egy üzenetsor, amelyben a bejövő adattömböket legfeljebb a maximálisan konfigurálható számú pufferelt adattömb puffereli. Ha eléri ezt a korlátot, az olvasó megvárja, amíg az üzeneteket a fenti réteg kiüríti az üzenetsorból (azaz csak az eredeti üzenettörzsből olvas), vagy amíg el nem éri a maximális fogadási időtúllépést.

Az adattömbcsatorna fogadási architektúrát bemutató diagram.

Adattömb programozási modell

A szolgáltatásfejlesztők az attribútum szerződésen belüli műveleteire való alkalmazásával ChunkingBehavior megadhatja, hogy mely üzenetek legyenek adattömbbe rendezve. Az attribútum egy AppliesTo tulajdonságot tesz elérhetővé, amely lehetővé teszi a fejlesztő számára annak megadását, hogy az adattömbök a bemeneti üzenetre, a kimeneti üzenetre vagy mindkettőre vonatkoznak-e. Az alábbi példa az attribútum használatát ChunkingBehavior mutatja be:

[ServiceContract]
interface ITestService
{
    [OperationContract]
    [ChunkingBehavior(ChunkingAppliesTo.Both)]
    Stream EchoStream(Stream stream);

    [OperationContract]
    [ChunkingBehavior(ChunkingAppliesTo.OutMessage)]
    Stream DownloadStream();

    [OperationContract(IsOneWay=true)]
    [ChunkingBehavior(ChunkingAppliesTo.InMessage)]
    void UploadStream(Stream stream);

}

Ebből a programozási modellből összeállítja azoknak a ChunkingBindingElement műveleti URI-knak a listáját, amelyek azonosítják az adattömbbe ágyazandó üzeneteket. A rendszer összehasonlítja az egyes kimenő üzenetek műveletet ezzel a listával annak megállapításához, hogy az üzenetet közvetlenül kell-e átszúrni vagy elküldeni.

A küldési művelet implementálása

Magas szinten a Küldés művelet először ellenőrzi, hogy a kimenő üzenetet át kell-e bontani, és ha nem, közvetlenül a belső csatornával küldi el az üzenetet.

Ha az üzenetet át kell bontani, a Send létrehoz egy újat ChunkingWriter , és meghívja WriteBodyContents a kimenő üzenetet, amely ezt ChunkingWriteradja át. Ekkor ChunkingWriter az üzenet adattömbje (beleértve az eredeti üzenetfejlécek másolását a kezdő adattömbüzenetbe) és adattömböket küld a belső csatornával.

Érdemes megjegyezni néhány részletet:

  • Az első hívások ThrowIfDisposedOrNotOpened elküldése annak ellenőrzéséhez, hogy a CommunicationState rendszer meg van-e nyitva.

  • A küldés szinkronizálva van, így minden munkamenethez egyszerre csak egy üzenet küldhető. Van egy ManualResetEvent elnevezett sendingDone név, amely vissza lesz állítva az adattömbben küldött üzenetek küldésekor. A záró adattömbüzenet elküldése után ez az esemény be van állítva. A Küldés metódus megvárja, amíg az esemény be lesz állítva, mielőtt megpróbálná elküldeni a kimenő üzenetet.

  • A Küldés zárolja a elemet, hogy megakadályozza a CommunicationObject.ThisLock szinkronizált állapot változásait küldés közben. Az állapotokkal és az állapotgéppel kapcsolatos CommunicationObject további információkért tekintse meg a CommunicationObject dokumentációt.

  • A Küldésnek átadott időtúllépés a teljes küldési művelet időtúllépése, amely magában foglalja az összes adattömb küldését is.

  • Az egyéni XmlDictionaryWriter kialakítás lett kiválasztva, hogy elkerülje a teljes eredeti üzenettörzs pufferelését. Ha az egész test használatával XmlDictionaryReader szereznénk egy message.GetReaderAtBodyContents holttestet, akkor pufferelnénk. Ehelyett van egy egyéniXmlDictionaryWriter, amely át lesz adva.message.WriteBodyContents Ahogy az üzenet meghívja a WriteBase64-et az írón, az író csomagokat csomagol az üzenetekbe, és elküldi őket a belső csatornán keresztül. A WriteBase64 blokkok, amíg el nem küldi az adattömböt.

A fogadási művelet megvalósítása

Magas szinten a Fogadás művelet először ellenőrzi, hogy a bejövő üzenet nem null , és hogy a művelet a ChunkingAction. Ha nem felel meg mindkét feltételnek, a rendszer változatlanul visszaadja az üzenetet a Fogadásból. Ellenkező esetben a Receive létrehoz egy új ChunkingReader és egy új ChunkingMessage burkolót (hívással GetNewChunkingMessage). Az új ChunkingMessageüzenet visszaadása előtt a Receive egy szálláncszálat használ a végrehajtáshoz ReceiveChunkLoop, amely egy hurokban hívja meg a hívásokat innerChannel.Receive , és leküldi az adattömböket addig ChunkingReader , amíg meg nem érkezik a teljes adattömbüzenet, vagy a fogadási időtúllépés el nem éri.

Érdemes megjegyezni néhány részletet:

  • A Küldéshez hasonlóan az első hívások ThrowIfDisposedOrNotOpened fogadása is meg van nyitva CommunicationState .

  • A fogadás is szinkronizálva van, így egyszerre csak egy üzenet fogadható a munkamenetből. Ez különösen azért fontos, mert ha egy kezdő adattömbüzenet érkezik, az összes további fogadott üzenet várhatóan az új adattömbsorozaton belül lesznek darabkák, amíg meg nem érkezik egy záró adattömbüzenet. A fogadás csak akkor tud üzeneteket lekérni a belső csatornáról, ha az aktuálisan kibontott üzenethez tartozó összes adattömb meg nem érkezik. Ennek megvalósításához a Receive egy ManualResetEvent elnevezett currentMessageCompletedüzenetet használ, amely a záró adattömbüzenet fogadásakor van beállítva, és új kezdő adattömbüzenet fogadásakor alaphelyzetbe áll.

  • A Küldés funkcióval ellentétben a fogadás nem akadályozza meg a szinkronizált állapotváltásokat a fogadás során. A bezárás meghívható például a fogadás során, és megvárhatja az eredeti üzenet függőben lévő fogadását vagy a megadott időtúllépési értéket.

  • A fogadásnak átadott időtúllépés a teljes fogadási művelet időtúllépése, amely magában foglalja az összes adattömb fogadását is.

  • Ha az üzenetet használó réteg a bejövő adattömbüzenetek sebességénél alacsonyabb sebességgel használja fel az üzenettörzset, a ChunkingReader pufferek a bejövő adattömböket a megadott ChunkingBindingElement.MaxBufferedChunkskorlátig pufferelik. A korlát elérése után a rendszer nem fog több adattömbet lekérni az alsó rétegből, amíg el nem éri a pufferelt adattömböket, vagy el nem éri a fogadási időtúllépést.

CommunicationObject felülbírálások

OnOpen

OnOpen hívásokkal innerChannel.Open nyissa meg a belső csatornát.

OnClose

OnClose először állítsa be stopReceive , hogy true jelezzen a függőben lévő ReceiveChunkLoop állapotnak. Ezután megvárja a receiveStoppedManualResetEventleálláskor ReceiveChunkLoop beállított értéket. Feltételezve, hogy a ReceiveChunkLoop megadott időtúllépésen belül leáll, OnClose a fennmaradó időtúllépéssel rendelkező hívások innerChannel.Close .

OnAbort

OnAbort a belső csatorna megszakítására irányuló hívások innerChannel.Abort . Függőben ReceiveChunkLoop lévő hívás esetén kivételt kap a függőben lévő innerChannel.Receive hívásból.

OnFaulted

Ez ChunkingChannel nem igényel különleges viselkedést, ha a csatorna hibás, ezért OnFaulted nincs felülbírált.

A Channel Factory implementálása

Az ChunkingChannelFactory a feladata, hogy létrehozza a belső csatorna-előállítóra való lépcsőzetes állapotváltások példányait ChunkingDuplexSessionChannel és azok kaszkádolt állapotát.

OnCreateChannel a belső csatorna-előállítót használja egy IDuplexSessionChannel belső csatorna létrehozásához. Ezután létrehoz egy új ChunkingDuplexSessionChannel átengedést ezen a belső csatornán, az adattömbbe illesztendő üzenetműveletek listájával és a fogadáskor pufferelendő adattömbök maximális számával együtt. Az összesíteni kívánt üzenetműveletek listája és a pufferbe hajtható adattömbök maximális száma két paraméter, ChunkingChannelFactory amelyeket a konstruktor átad. A szakasz azt ismerteti, ChunkingBindingElement hogy ezek az értékek honnan származnak.

A OnOpen, OnCloseOnAbort és azok aszinkron megfelelői a megfelelő állapotáttrasztálási metódust hívják a belső csatornagyárban.

Csatornafigyelő implementálása

Ez ChunkingChannelListener egy burkoló egy belső csatornafigyelő körül. Fő funkciója a belső csatorna figyelőjének küldött hívásokon kívül az, hogy újakat ChunkingDuplexSessionChannels burkoljon a belső csatorna figyelője által elfogadott csatornák köré. Ez a művelet a következőben OnAcceptChannel történik: és OnEndAcceptChannel. Az újonnan létrehozott ChunkingDuplexSessionChannel csatornát a rendszer a korábban ismertetett paraméterekkel együtt átadja a belső csatornának.

Kötéselem és kötés implementálása

ChunkingBindingElementfelelős az és ChunkingChannelFactorya ChunkingChannelListener . A ChunkingBindingElement rendszer ellenőrzi, hogy a T ésCanBuildChannelFactory<>CanBuildChannelListener a T<> típusú-e IDuplexSessionChannel (az adattömbcsatorna által támogatott egyetlen csatorna), és hogy a kötés többi kötési eleme támogatja-e ezt a csatornatípust.

BuildChannelFactory <T> először ellenőrzi, hogy a kért csatornatípus felépíthető-e, majd lekéri az adattömbbe beszúrandó üzenetműveletek listáját. További információkért lásd a következő szakaszt. Ezután létrehoz egy új ChunkingChannelFactory átadást a belső csatorna-előállítóban (a visszaadott módon), az üzenetműveletek listájában context.BuildInnerChannelFactory<IDuplexSessionChannel>, valamint a pufferelendő adattömbök maximális számában. Az adattömbök maximális száma a függvény által MaxBufferedChunksközzétett ChunkingBindingElement tulajdonságból származik.

BuildChannelListener<T> hasonló implementációval rendelkezik a belső csatorna figyelőjének létrehozására ChunkingChannelListener és átadására.

Ebben a példában TcpChunkingBindingegy példakötés szerepel. Ez a kötés két kötéselemből áll: TcpTransportBindingElement és ChunkingBindingElement. A tulajdonság felfedése MaxBufferedChunks mellett a kötés néhány tulajdonságot is beállít TcpTransportBindingElement , például MaxReceivedMessageSize (a fejlécekhez +100 KB bájtra állítja ChunkingUtils.ChunkSize ).

TcpChunkingBindinga metódusból IBindingRuntimePreferences is igaz értéket ad ReceiveSynchronously vissza, és azt jelzi, hogy csak a szinkron fogadási hívások vannak implementálva.

Az adattömbbe illesztendő üzenetek meghatározása

Az adattömbcsatorna csak az attribútumon keresztül ChunkingBehavior azonosított üzeneteket darabozza el. Az ChunkingBehavior osztály implementálja IOperationBehavior és implementálja a metódus meghívásával AddBindingParameter . Ebben a módszerben a ChunkingBehavior tulajdonságAppliesTo (vagy mindkettő) értékét InMessage vizsgálja annak meghatározásához, OutMessage hogy mely üzenetek legyenek adattömbök. Ezután lekéri az egyes üzenetek műveletet (az Üzenetek gyűjteményből OperationDescription), és hozzáadja azt a példányban található sztringgyűjteményhez ChunkingBindingParameter. Ezután hozzáadja ezt ChunkingBindingParameter a megadotthoz BindingParameterCollection.

Ezt BindingParameterCollection a BindingContext kötés minden egyes kötési elemének átadja, amikor a kötéselem létrehozza a csatorna-előállítót vagy a csatornafigyelőt. Az ChunkingBindingElement's implementációja BuildChannelFactory<T> , és BuildChannelListener<T> húzza ki ezt ChunkingBindingParameter az BindingContext's BindingParameterCollection. A benne található ChunkingBindingParameter műveletek gyűjteményét a következőnek továbbítja a ChunkingChannelFactory következőnek: vagy ChunkingChannelListener, amely viszont átadja azt a ChunkingDuplexSessionChannel.

A minta futtatása

A minta beállítása, összeállítása és futtatása

  1. Telepítse a ASP.NET 4.0-t az alábbi paranccsal.

    %windir%\Microsoft.NET\Framework\v4.0.XXXXX\aspnet_regiis.exe /i /enable
    
  2. Győződjön meg arról, hogy elvégezte a Windows Communication Foundation-minták egyszeri beállítási eljárását.

  3. A megoldás létrehozásához kövesse a Windows Communication Foundation-minták készítésére vonatkozó utasításokat.

  4. Ha a mintát egy vagy több gép közötti konfigurációban szeretné futtatni, kövesse a Windows Communication Foundation-minták futtatásával kapcsolatos utasításokat.

  5. Először futtassa Service.exe, majd futtassa Client.exe, és figyelje mindkét konzolablak kimenetét.

A minta futtatásakor a következő kimenet várható.

Ügyfél:

Press enter when service is available

 > Sent chunk 1 of message 867c1fd1-d39e-4be1-bc7b-32066d7ced10
 > Sent chunk 2 of message 867c1fd1-d39e-4be1-bc7b-32066d7ced10
 > Sent chunk 3 of message 867c1fd1-d39e-4be1-bc7b-32066d7ced10
 > Sent chunk 4 of message 867c1fd1-d39e-4be1-bc7b-32066d7ced10
 > Sent chunk 5 of message 867c1fd1-d39e-4be1-bc7b-32066d7ced10
 > Sent chunk 6 of message 867c1fd1-d39e-4be1-bc7b-32066d7ced10
 > Sent chunk 7 of message 867c1fd1-d39e-4be1-bc7b-32066d7ced10
 > Sent chunk 8 of message 867c1fd1-d39e-4be1-bc7b-32066d7ced10
 > Sent chunk 9 of message 867c1fd1-d39e-4be1-bc7b-32066d7ced10
 > Sent chunk 10 of message 867c1fd1-d39e-4be1-bc7b-32066d7ced10
 < Received chunk 1 of message 5b226ad5-c088-4988-b737-6a565e0563dd
 < Received chunk 2 of message 5b226ad5-c088-4988-b737-6a565e0563dd
 < Received chunk 3 of message 5b226ad5-c088-4988-b737-6a565e0563dd
 < Received chunk 4 of message 5b226ad5-c088-4988-b737-6a565e0563dd
 < Received chunk 5 of message 5b226ad5-c088-4988-b737-6a565e0563dd
 < Received chunk 6 of message 5b226ad5-c088-4988-b737-6a565e0563dd
 < Received chunk 7 of message 5b226ad5-c088-4988-b737-6a565e0563dd
 < Received chunk 8 of message 5b226ad5-c088-4988-b737-6a565e0563dd
 < Received chunk 9 of message 5b226ad5-c088-4988-b737-6a565e0563dd
 < Received chunk 10 of message 5b226ad5-c088-4988-b737-6a565e0563dd

Kiszolgáló:

Service started, press enter to exit
 < Received chunk 1 of message 867c1fd1-d39e-4be1-bc7b-32066d7ced10
 < Received chunk 2 of message 867c1fd1-d39e-4be1-bc7b-32066d7ced10
 < Received chunk 3 of message 867c1fd1-d39e-4be1-bc7b-32066d7ced10
 < Received chunk 4 of message 867c1fd1-d39e-4be1-bc7b-32066d7ced10
 < Received chunk 5 of message 867c1fd1-d39e-4be1-bc7b-32066d7ced10
 < Received chunk 6 of message 867c1fd1-d39e-4be1-bc7b-32066d7ced10
 < Received chunk 7 of message 867c1fd1-d39e-4be1-bc7b-32066d7ced10
 < Received chunk 8 of message 867c1fd1-d39e-4be1-bc7b-32066d7ced10
 < Received chunk 9 of message 867c1fd1-d39e-4be1-bc7b-32066d7ced10
 < Received chunk 10 of message 867c1fd1-d39e-4be1-bc7b-32066d7ced10
 > Sent chunk 1 of message 5b226ad5-c088-4988-b737-6a565e0563dd
 > Sent chunk 2 of message 5b226ad5-c088-4988-b737-6a565e0563dd
 > Sent chunk 3 of message 5b226ad5-c088-4988-b737-6a565e0563dd
 > Sent chunk 4 of message 5b226ad5-c088-4988-b737-6a565e0563dd
 > Sent chunk 5 of message 5b226ad5-c088-4988-b737-6a565e0563dd
 > Sent chunk 6 of message 5b226ad5-c088-4988-b737-6a565e0563dd
 > Sent chunk 7 of message 5b226ad5-c088-4988-b737-6a565e0563dd
 > Sent chunk 8 of message 5b226ad5-c088-4988-b737-6a565e0563dd
 > Sent chunk 9 of message 5b226ad5-c088-4988-b737-6a565e0563dd
 > Sent chunk 10 of message 5b226ad5-c088-4988-b737-6a565e0563dd