Öbekleme Kanalı

ChunkingChannel örneği, özel bir protokolün veya katmanlı kanalın rastgele büyük iletileri öbekleme ve atlama işlemi yapmak için nasıl kullanılabileceğini gösterir.

Windows Communication Foundation (WCF) kullanarak büyük iletiler gönderirken, genellikle bu iletileri arabelleğe almak için kullanılan bellek miktarını sınırlamak istenir. Olası çözümlerden biri ileti gövdesinin akışını yapmaktır (verilerin büyük bir kısmının gövdede olduğu varsayılarak). Ancak bazı protokoller iletinin tamamını arabelleğe almayı gerektirir. Güvenilir mesajlaşma ve güvenlik bu tür iki örnektir. Başka bir olası çözüm, büyük iletiyi öbek adı verilen daha küçük iletilere bölmek, bu öbekleri birer birer bir öbek göndermek ve büyük iletiyi alıcı tarafında yeniden oluşturmaktır. Uygulamanın kendisi bu öbekleme ve öbek kaldırma işlemini gerçekleştirebilir veya bunu yapmak için özel bir kanal kullanabilir.

Öbekleme her zaman yalnızca gönderilecek iletinin tamamı oluşturulduktan sonra kullanılmalıdır. Öbekleme kanalı her zaman bir güvenlik kanalının ve güvenilir bir oturum kanalının altına katmanlanmalıdır.

Not

Bu örnek için kurulum yordamı ve derleme yönergeleri bu konunun sonunda yer alır.

Kanal Varsayımlarını ve Sınırlamalarını Öbekleme

İleti Yapısı

Öbekleme kanalı, iletilerin öbeklenmesi için aşağıdaki ileti yapısını varsayar:

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

ServiceModel kullanılırken, 1 giriş parametresine sahip sözleşme işlemleri, giriş iletisi için bu ileti şekliyle uyumlu olur. Benzer şekilde, 1 çıkış parametresi veya dönüş değeri olan sözleşme işlemleri, çıkış iletisi için bu ileti şekliyle uyumludur. Aşağıda bu tür işlemlere örnekler verilmiştir:

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

    [OperationContract]
    Stream DownloadStream();

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

Oturumlar

Öbekleme kanalı, iletilerin sıralı tesliminde (öbekler) tam olarak bir kez teslim edilmesi gerekir. Bu, temel alınan kanal yığınının oturumlu olması gerektiği anlamına gelir. Oturumlar aktarım (örneğin, TCP aktarımı) veya oturumlu bir protokol kanalı (örneğin ReliableSession kanalı) tarafından sağlanabilir.

Zaman Uyumsuz Gönderme ve Alma

Zaman uyumsuz gönderme ve alma yöntemleri, öbekleme kanalı örneğinin bu sürümünde uygulanmaz.

Öbekleme Protokolü

Öbekleme kanalı, bir öbek dizisinin başlangıcını ve sonunu ve her öbek sırasını gösteren bir protokol tanımlar. Aşağıdaki üç örnek ileti, başlangıç, öbek ve bitiş iletilerini, her birinin önemli yönlerini açıklayan açıklamalarla gösterir.

İletiyi Başlat

<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>

Öbek İletisi

<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>

İletiyi Sonlandır

<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>

Kanal Mimarisi öbekleme

Öbekleme kanalı, yüksek düzeyde tipik kanal mimarisini izleyen bir IDuplexSessionChannel kanaldır. ChunkingBindingElement ve oluşturabilen ChunkingChannelFactory bir ChunkingChannelListenervardır. , ChunkingChannelFactory istendiğinde örneklerini ChunkingChannel oluşturur. , ChunkingChannelListener yeni bir iç kanalın ChunkingChannel kabul edildiği örnekleri oluşturur. İleti ChunkingChannel göndermek ve almak kendi sorumluluğundadır.

Bir sonraki düzeyde, ChunkingChannel öbekleme protokollerini uygulamak için birkaç bileşene dayanır. Gönderme tarafında kanal, gerçek öbekleme işlemini yerine getiren adlı ChunkingWriter özel XmlDictionaryWriter bir ad kullanır. ChunkingWriter öbekleri göndermek için doğrudan iç kanalı kullanır. Özel XmlDictionaryWriter kullanmak, özgün iletinin büyük gövdesi yazılırken öbek göndermemizi sağlar. Bu, özgün iletinin tamamını arabelleğe almadığımız anlamına gelir.

Öbek kanalı gönderme mimarisini gösteren diyagram.

Alma tarafında, ChunkingChannel iletileri iç kanaldan çeker ve gelen öbeklerden özgün iletiyi yeniden oluşturan adlı ChunkingReaderbir özel XmlDictionaryReader iletiye iletir. ChunkingChannelbunu ChunkingReader adlı ChunkingMessage özel Message bir uygulamada sarmalar ve bu iletiyi yukarıdaki katmana döndürür. bu ve ChunkingMessage bileşimiChunkingReader, özgün ileti gövdesinin tamamını arabelleğe almak zorunda kalmak yerine yukarıdaki katman tarafından okunmakta olan özgün ileti gövdesinin öbeklerini kaldırmamıza olanak tanır. ChunkingReader , gelen öbekleri en fazla yapılandırılabilir arabelleğe alınmış öbek sayısına kadar arabelleğe aldığı bir kuyruğa sahiptir. Bu üst sınıra ulaşıldığında, okuyucu iletilerin kuyruktan yukarıdaki katman tarafından boşaltılması için (yani, yalnızca özgün ileti gövdesinden okuyarak) veya maksimum alma zaman aşımına ulaşılana kadar bekler.

Öbekleme kanalı alma mimarisini gösteren diyagram.

Programlama Modelini Öbekleme

Hizmet geliştiricileri, özniteliği sözleşmedeki işlemlere uygulayarak hangi iletilerin ChunkingBehavior öbekleneceğini belirtebilir. özniteliği, geliştiricinin öbeklemenin giriş iletisine mi, çıkış iletisine mi yoksa her ikisine mi uygulanacağını belirtmesine olanak tanıyan bir AppliesTo özellik sunar. Aşağıdaki örnekte özniteliğin kullanımı gösterilmektedir ChunkingBehavior :

[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);

}

Bu programlama modelinden ChunkingBindingElement , öbeklenecek iletileri tanımlayan eylem URI'lerinin listesini derler. Her giden iletinin eylemi, iletinin öbeklenmesi mi yoksa doğrudan gönderilmesi mi gerektiğini belirlemek için bu listeyle karşılaştırılır.

Gönderme İşlemi Uygulama

Yüksek düzeyde, Gönder işlemi önce giden iletinin öbeklenip öbeklenmemesi gerektiğini denetler ve değilse, iletiyi doğrudan iç kanalı kullanarak gönderir.

İletinin öbeklenmesi gerekiyorsa, Gönder yeni ChunkingWriter bir oluşturur ve giden iletide bunu ChunkingWriterileten çağrılarWriteBodyContents. ardından ChunkingWriter , ileti öbeklemesi yapar (özgün ileti üst bilgilerini başlangıç öbek iletisine kopyalama dahil) ve iç kanalı kullanarak öbekler gönderir.

Dikkate değer birkaç ayrıntı:

  • öğesinin açıldığından emin olmak için ilk çağrıları ThrowIfDisposedOrNotOpened CommunicationState gönderin.

  • Gönderme eşitlenir, böylece her oturum için aynı anda yalnızca bir ileti gönderilebilir. Öbeklenmiş bir ManualResetEvent ileti gönderilirken sıfırlanan adlı bir ad sendingDone vardır. Uç öbek iletisi gönderildikten sonra bu olay ayarlanır. Send yöntemi, giden iletiyi göndermeye çalışmadan önce bu olayın ayarlanmasını bekler.

  • Gönder, gönderirken eşitlenmiş durum değişikliklerini önlemek için öğesini kilitler CommunicationObject.ThisLock . CommunicationObject Durumlar ve durum makinesi hakkında CommunicationObject daha fazla bilgi için belgelere bakın.

  • Gönder'e geçirilen zaman aşımı, tüm öbeklerin gönderilmesini içeren gönderme işleminin tamamı için zaman aşımı olarak kullanılır.

  • Özgün ileti gövdesinin tamamını arabelleğe almaktan kaçınmak için özel XmlDictionaryWriter tasarım seçildi. Eğer cesedin tamamını kullanarak message.GetReaderAtBodyContents bir ceset alırsak XmlDictionaryReader arabelleğe alınırdı. Bunun yerine, öğesine message.WriteBodyContentsgeçirilen bir özel XmlDictionaryWriter öğemiz var. İleti yazıcıda WriteBase64'i çağırdıkça, yazıcı öbekleri iletilere paketler ve iç kanalı kullanarak gönderir. Öbek gönderilene kadar WriteBase64 blokları.

Alma İşlemi Uygulama

Yüksek düzeyde, Receive işlemi önce gelen iletinin olmadığını null ve eyleminin ChunkingActionolduğunu denetler. Her iki ölçüte de uymazsa, ileti Alış'tan değiştirilmeden döndürülür. Aksi takdirde, Receive yeni ChunkingReader bir ve çevresinde sarmalanmış yeni ChunkingMessage bir oluşturur (çağırarak GetNewChunkingMessage). Bu yeni ChunkingMessageöğesini döndürmeden önce Receive, bir ReceiveChunkLoopdöngüde çağrısı innerChannel.Receive yapan ve öbekleri son öbek iletisi alınana veya alma zaman aşımına ulaşana ChunkingReader kadar öğesine teslim eden bir iş parçacığı havuzu iş parçacığı kullanır.

Dikkate değer birkaç ayrıntı:

  • Gönder gibi, Aç olduğundan emin olmak için ilk çağrıları ThrowIfDisposedOrNotOpened CommunicationState alın.

  • Aynı anda oturumdan yalnızca bir ileti alınabilmesi için alma da eşitlenir. Bu özellikle önemlidir çünkü bir başlangıç öbek iletisi alındıktan sonra, bir son öbek iletisi alınana kadar sonraki tüm alınan iletilerin bu yeni öbek dizisi içinde öbekler olması beklenir. Alma, öbekleri kaldırılmakta olan iletiye ait tüm öbekler alınana kadar iç kanaldan iletileri çekemez. Bunu gerçekleştirmek için, Receive adlı currentMessageCompletedbir ManualResetEvent kullanır. Bu, bitiş öbek iletisi alındığında ayarlanır ve yeni bir başlangıç öbek iletisi alındığında sıfırlanır.

  • Gönder'in aksine Alma, alma sırasında eşitlenmiş durum geçişlerini engellemez. Örneğin, Kapat alınırken çağrılabilir ve özgün iletinin bekleyen alınması tamamlanana veya belirtilen zaman aşımı değerine ulaşılana kadar bekler.

  • Alma işlemine geçirilen zaman aşımı, tüm öbekleri almayı da içeren alma işleminin tamamı için zaman aşımı olarak kullanılır.

  • İletiyi kullanan katman, ileti gövdesini gelen öbek iletilerinin hızından daha düşük bir hızda tüketiyorsa, ChunkingReader bu gelen öbekleri tarafından ChunkingBindingElement.MaxBufferedChunksbelirtilen sınıra kadar arabelleğe alır. Bu sınıra ulaşıldıktan sonra, arabelleğe alınan bir öbek tüketilene veya alma zaman aşımına ulaşılana kadar alt katmandan başka öbek çekilmez.

CommunicationObject Geçersiz Kılmaları

OnOpen

OnOpen iç kanalı açmak için aramalar innerChannel.Open .

OnClose

OnCloseönce beklemede ReceiveChunkLoop olanın durması için sinyal vermek için öğesini ayarlar.stopReceive true Ardından durdurulduğunda ayarlanan öğesini bekler receiveStopped ManualResetEvent.ReceiveChunkLoop ReceiveChunkLoop Belirtilen zaman aşımı içinde durduğunu varsayarsak, OnClose kalan zaman aşımıyla birlikte çağrılarinnerChannel.Close.

OnAbort

OnAbort iç kanalı durdurmak için çağrılar innerChannel.Abort . Bekleyen ReceiveChunkLoop bir çağrı varsa, bekleyen innerChannel.Receive çağrıdan bir özel durum alır.

OnFaulted

ChunkingChannel kanal hatalı olduğunda özel davranış gerektirmez, bu nedenle OnFaulted geçersiz kılınmaz.

Channel Factory Uygulama

, ChunkingChannelFactory ve örneklerinin oluşturulmasından ChunkingDuplexSessionChannel ve durum geçişlerinin iç kanal fabrikasına basamaklanmasından sorumludur.

OnCreateChannel iç kanal oluşturmak IDuplexSessionChannel için iç kanal fabrikasını kullanır. Ardından, bu iç kanala, öbeklenecek ileti eylemlerinin listesi ve alma sırasında arabelleğe alınacak en fazla öbek sayısıyla birlikte yeni ChunkingDuplexSessionChannel bir geçiş oluşturur. Öbeklenecek ileti eylemlerinin listesi ve arabelleğe alınacak en fazla öbek sayısı, oluşturucusunda geçirilen ChunkingChannelFactory iki parametredir. üzerindeki ChunkingBindingElement bölümünde bu değerlerin nereden geldiği açıklanmaktadır.

OnOpen, OnCloseOnAbort ve zaman uyumsuz eşdeğerleri, iç kanal fabrikasında ilgili durum geçiş yöntemini çağırır.

Kanal Dinleyicisi Uygulama

ChunkingChannelListener, bir iç kanal dinleyicisinin etrafındaki sarmalayıcıdır. Ana işlevi, bu iç kanal dinleyicisine yapılan temsilci çağrılarının yanı sıra, iç kanal dinleyicisinden kabul edilen kanalların çevresinde yenileri ChunkingDuplexSessionChannels kaydırmaktır. Bu işlem ve OnEndAcceptChanneliçinde OnAcceptChannel yapılır. Yeni oluşturulan ChunkingDuplexSessionChannel , daha önce açıklanan diğer parametrelerle birlikte iç kanala geçirilir.

Bağlama Öğesini ve Bağlamayı Uygulama

ChunkingBindingElementve ChunkingChannelListeneroluşturmakla ChunkingChannelFactory sorumludur. , ChunkingBindingElement T ve CanBuildChannelListener<> T içindeki CanBuildChannelFactory<T'nin> türünde IDuplexSessionChannel olup olmadığını (öbekleme kanalı tarafından desteklenen tek kanal) ve bağlamadaki diğer bağlama öğelerinin bu kanal türünü destekleyip desteklemediğini denetler.

BuildChannelFactory<T> önce istenen kanal türünün derlenip derlenebileceğini denetler ve ardından öbeklenecek ileti eylemlerinin listesini alır. Daha fazla bilgi için aşağıdaki bölüme bakın. Ardından iç kanal fabrikasını (öğesinden context.BuildInnerChannelFactory<IDuplexSessionChannel>döndürüldükçe) ileti eylemleri listesini ve arabelleğe alınacak en fazla öbek sayısını geçirerek yeni ChunkingChannelFactory bir oluşturur. Öbek sayısı üst sınırı, tarafından ChunkingBindingElementkullanıma sunulan adlı MaxBufferedChunks bir özellikten gelir.

BuildChannelListener<T> , iç kanal dinleyicisini oluşturmak ChunkingChannelListener ve geçirmek için benzer bir uygulamaya sahiptir.

Bu örnekte adlı TcpChunkingBindingbir örnek bağlama vardır. Bu bağlama iki bağlama öğesinden oluşur: TcpTransportBindingElement ve ChunkingBindingElement. Bağlama, özelliğini kullanıma açmanın MaxBufferedChunks yanı sıra gibi MaxReceivedMessageSize bazı TcpTransportBindingElement özellikleri de ayarlar (üst bilgiler için + 100 KB bayt olarak ayarlar ChunkingUtils.ChunkSize ).

TcpChunkingBinding ayrıca yalnızca zaman uyumlu Alma çağrılarının IBindingRuntimePreferences uygulandığını belirten yönteminden ReceiveSynchronously true uygular ve döndürür.

Öbek alınacak iletileri belirleme

Öbekleme kanalı yalnızca özniteliği aracılığıyla ChunkingBehavior tanımlanan iletileri öbekler. ChunkingBehavior sınıfı IOperationBehavior yöntemini çağırarak AddBindingParameter uygular ve uygulanır. Bu yöntemdeChunkingBehavior, hangi iletilerin öbeklenmesi gerektiğini belirlemek için özelliğinin AppliesTo (InMessageOutMessageveya her ikisinin) değerini inceler. Ardından bu iletilerin her birinin eylemini alır (üzerindeki OperationDescriptionİletiler koleksiyonundan) ve bir örneğinin içinde yer alan dize koleksiyonuna ChunkingBindingParameterekler. Ardından bunu ChunkingBindingParameter sağlanan BindingParameterCollectionöğesine ekler.

Bu BindingParameterCollection bağlama öğesi kanal fabrikasını BindingContext veya kanal dinleyicisini oluştururken bağlamadaki her bağlama öğesine içinde geçirilir. 'ChunkingBindingElementnin uygulaması BuildChannelFactory<T> ve BuildChannelListener<T> bunu ChunkingBindingParameter içinden BindingParameterCollectionçekinBindingContext'. içinde ChunkingBindingParameter yer alan eylemlerin koleksiyonu daha sonra veya ChunkingChannelListeneröğesine geçirilir ChunkingChannelFactory ve bu da bunu öğesine ChunkingDuplexSessionChannelgeçirir.

Örneği Çalıştırma

Örneği ayarlamak, derlemek ve çalıştırmak için

  1. Aşağıdaki komutu kullanarak ASP.NET 4.0'ı yükleyin.

    %windir%\Microsoft.NET\Framework\v4.0.XXXXX\aspnet_regiis.exe /i /enable
    
  2. Windows Communication Foundation Örnekleri için Tek Seferlik Kurulum Yordamı'nı gerçekleştirdiğinizden emin olun.

  3. Çözümü oluşturmak için Windows Communication Foundation Örnekleri Oluşturma başlığındaki yönergeleri izleyin.

  4. Örneği tek veya makineler arası bir yapılandırmada çalıştırmak için Windows Communication Foundation Örneklerini Çalıştırma başlığındaki yönergeleri izleyin.

  5. önce Service.exe çalıştırın, ardından Client.exe çalıştırın ve çıkış için her iki konsol penceresini de izleyin.

Örnek çalıştırılırken aşağıdaki çıkış beklenir.

İstemci:

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

Sunucu:

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