2016-12-21 44 views
1

我有一個C#類來創建消息。在C中將消息分塊成更小的塊#

public class ExMessage 
    { 
     private UInt16 m_SendingId = 123; 
     private byte m_control_byte_1; 
     private enum destination_service : byte 
     { 
      serv_1 = 0x0, 
      serv_2 = 0x1 
     }; 
     private byte m_pd; 
     private byte m_filler_bytes; 
     private byte[] m_payload; 

     public byte[] Payload 
     { 
      get 
      { 
       return m_payload; 
      } 
     } 


     /// <summary> 
     /// Constructor. 
     /// </summary> 
     public ExMessage(byte[] payload) 
     { 
      m_pd = 0x0; 
      m_control_byte_1 = 0xA5; 
      m_payload = payload; 
      m_filler_bytes = 0xF; 

     } 

     protected void WriteBody(Stream stream) 
     { 
      stream.WriteByte(m_control_byte_1); 
      stream.WriteByte(0x0); 

      stream.WriteWordLittleEndian(m_SendingId); 
      stream.WriteByte((byte)destination_service.serv_2); 

      stream.WriteByte((byte)m_pd); // payload details 

      stream.WriteByte((byte)m_payload.Length); //write the payload length 

      var count = 0; 
      while (count < m_payload.Length) //copy over the actual payload. 
      { 
       stream.WriteByte((byte)m_payload[count]); 
       count++; 
      } 

      var len = 48 - (5 + m_payload.Length); 
      count = 0; 
      while (count < len) //copy over spare bytes 0x3 
      { 
       stream.WriteByte(m_filler_bytes); 
       count++; 
      } 
     } 

     public byte[] ToBytes() 
     { 
      MemoryStream stream = new MemoryStream(); 
      WriteBody(stream); 

      return stream.ToArray(); 
     } 

我創建消息如下

var Message = new ExMessage(Encoding.UTF8.GetBytes("HelloWorld")); 

現在我的使用情況如下。

1)我使用的協議在有效負載上施加了40個字節的大小限制。如果我傳遞的有效負載中的字節數大於40字節,則應將其分解爲兩條消息。

2)有沒有辦法讓構造函數根據我傳入的字節數組的大小返回一個ExMessage對象列表。

3)如果不是,什麼是處理這種情況

+2

幾點意見,有些獨立於以下問題: - 如果事先不知道大小,遞增寫入MemoryStream效率不高。這是因爲調整了內部緩衝區。看起來就像你會知道它。鑑於此,即使您逐漸寫入,也要預先確定流的大小,以確保它足夠長,以便用於整個塊。 - 小心讓一個MemoryStream變得太大。查看關於.net 中的大型對象的文檔 - 不需要增量寫入m_payload,而是用一次Write()調用立即寫入整個塊 –

回答

3

在這裏,最好的辦法是我會怎麼做:

var size = 4; 
var messages = 
    Encoding.UTF8.GetBytes("HelloWorld") //48 65 6C 6C 6F 57 6F 72 6C 64 
     .Select((b, i) => new { b, i }) // Enumerable of byte and index 
     .GroupBy(x => x.i/size, x => x.b) // group by index divide by block size 
     .Select(x => new ExMessage(x.ToArray())); // create messages 

這給了我:

messages

你將執行它像這樣:

public class ExMessage 
{ 
    private const int __size = 4; 
    public static ExMessage[] Create(byte[] payload) 
    { 
     return payload 
      .Select((b, i) => new { b, i }) 
       .GroupBy(x => x.i/__size, x => x.b) 
       .Select(x => new ExMessage(x.ToArray())) 
       .ToArray(); 
    } 
    /* rest of class */ 
} 

你會再這樣稱呼它:

var messages = ExMessage.Create(Encoding.UTF8.GetBytes("HelloWorld")); 
+0

上述解決方案需要什麼軟件包。它需要C#反應式擴展嗎?如果是這樣,我寧願避免它。 – liv2hak

+0

@ liv2hak - 不,它只是標準的LINQ。 – Enigmativity

+0

我無法理解這個邏輯。請給我多解釋一下 – liv2hak

1

我會使用上ExMessage靜態函數,這樣的事情:

class ExMessage 
{ 
    ... 
    public static List<ExMessage> CreateMessages(byte[] payload) 
    { 
     List<byte[]> chunks = ... split payload into 40byte chunks... 
     return chunks.Select(p => new ExMessage(p).ToList();  
    } 
    ... 
}