Jegyzet
Az oldalhoz való hozzáférés engedélyezést igényel. Próbálhatod be jelentkezni vagy könyvtárat váltani.
Az oldalhoz való hozzáférés engedélyezést igényel. Megpróbálhatod a könyvtár váltását.
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.
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.
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
ThrowIfDisposedOrNotOpenedelküldése annak ellenőrzéséhez, hogy aCommunicationStaterendszer meg van-e nyitva.A küldés szinkronizálva van, így minden munkamenethez egyszerre csak egy üzenet küldhető. Van egy
ManualResetEventelnevezettsendingDonené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.ThisLockszinkronizá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.GetReaderAtBodyContentsholttestet, akkor pufferelnénk. Ehelyett van egy egyéniXmlDictionaryWriter, amely át lesz adva.message.WriteBodyContentsAhogy 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
ThrowIfDisposedOrNotOpenedfogadása is meg van nyitvaCommunicationState.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
ManualResetEventelnevezettcurrentMessageCompletedü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
ChunkingReaderpufferek a bejövő adattömböket a megadottChunkingBindingElement.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
Telepítse a ASP.NET 4.0-t az alábbi paranccsal.
%windir%\Microsoft.NET\Framework\v4.0.XXXXX\aspnet_regiis.exe /i /enableGyőződjön meg arról, hogy elvégezte a Windows Communication Foundation-minták egyszeri beállítási eljárását.
A megoldás létrehozásához kövesse a Windows Communication Foundation-minták készítésére vonatkozó utasításokat.
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.
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