程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 介紹開源的.net通信框架NetworkComms框架之四 消息邊界,.netnetworkcomms

介紹開源的.net通信框架NetworkComms框架之四 消息邊界,.netnetworkcomms

編輯:C#入門知識

介紹開源的.net通信框架NetworkComms框架之四 消息邊界,.netnetworkcomms


原文網址: http://www.cnblogs.com/csdev

Networkcomms 是一款C# 語言編寫的TCP/UDP通信框架  作者是英國人  以前是收費的 目前作者已經開源  許可是:Apache License v2

開源地址是:https://github.com/MarcFletcher/NetworkComms.Net

首先,使用TCP通信的時候存在消息邊界的問題,也就是如何處理粘包問題,networkcomms 框架本身已經對這個問題有內置的解決方案,我們在使用框架時直接數據通信即可,不需要關心消息邊界問題。

下面我們來分析一下networkcomms對消息邊界問題是如何進行處理的。

 TCP無保護消息邊界的解決
 針對這個問題,一般有3種解決方案:

      (1)發送固定長度的消息

      (2)把消息的尺寸與消息一塊發送

      (3)使用特殊標記來區分消息間隔

NetworkComms通信框架使用的是第二種   即消息的尺寸與消息一塊發送

 

來看一下這個流程

客戶端發送一個類給服務器端

代碼如下:

  User  user1=new User ();
  user1.UserID="10000";
  user1.Name="天涯共此時";
       

connection.SendObject("消息類型", user1);

然後networkcomms框架開始發送這個類

在ConnectionSendClose.cs文件中

判斷發送的類,是否是Packet類型,如果是使用SendPacket進行發送。如果不是,轉換成Packet類型再發送

   public void SendObject<sendObjectType>(string sendingPacketType, sendObjectType objectToSend, SendReceiveOptions options, out long packetSequenceNumber)
        {
//判斷發送的類,是否是Packet類型 Packet objectToSendAsPacket = objectToSend as Packet; if (objectToSendAsPacket == null) {
//如果不是,轉換成Packet類型再發送 using (Packet sendPacket = new Packet(sendingPacketType, objectToSend, options)) SendPacket<sendObjectType>(sendPacket, out packetSequenceNumber); } else { if (objectToSendAsPacket.PacketHeader.PacketType != sendingPacketType) throw new ArgumentException("Unable to send object of type Packet if the PacketHeader.PacketType and sendingPacketType do not match."); SendPacket<sendObjectType>(objectToSendAsPacket, out packetSequenceNumber); } }

上面的代碼中,通過這一句

Packet sendPacket = new Packet(sendingPacketType, objectToSend, options)
把要發送的User類轉化為Packet類

來分析一下Packet類

 public Packet(string sendingPacketTypeStr, string requestReturnPacketTypeStr, object payloadObject, SendReceiveOptions options)
        {
            Constructor(sendingPacketTypeStr, requestReturnPacketTypeStr, payloadObject, options, false);
        }

 

要發送的數據類(此次為User類型數據),以參數的形式賦值給Packet.

Packet類,經過一些類內部處理,User類數據,最後經過轉化存放在PacketData屬性中,也就是包體數據。

Packet類中的SerialiseHeader(SendReceiveOptions options)返回的是包頭(PacketHeader)序列化後的數據

Connection類中的SendPacketSpecific方法會先發送包頭數據,再發送包體數據。

我們看一下Packet中序列化包頭的方法

   /// <inheritdoc />
        public byte[] SerialiseHeader(SendReceiveOptions options)
        {
            if (options == null) throw new ArgumentNullException("options", "Provided SendReceiveOptions cannot be null.");

            //We need to start of by serialising the header
            //把包頭序列化為二進制數組
            byte[] serialisedHeader;
            using (StreamTools.StreamSendWrapper sendWrapper = options.DataSerializer.SerialiseDataObject(_packetHeader, options.DataProcessors, null))
                serialisedHeader = sendWrapper.ThreadSafeStream.ToArray(1);

            if (serialisedHeader.Length - 1 > byte.MaxValue)
                throw new SerialisationException("Unable to send packet as header size is larger than Byte.MaxValue. Try reducing the length of provided packetTypeStr or turning off checkSum validation.");

            //The first byte now specifies the header size (allows for variable header size)
            //包頭轉化成的二進制數據,第一個字節的值,設定為包頭的長度
            serialisedHeader[0] = (byte)(serialisedHeader.Length - 1);

            if (serialisedHeader == null)
                throw new SerialisationException("Serialised header bytes should never be null.");

            return serialisedHeader;
        }

 

原文網址: http://www.cnblogs.com/csdev

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved