簡體   English   中英

.NET中位的表示形式及其序列化

[英]Representation of bits and their serialisation in .Net

我正在練習實現一些基本的第7層協議,但是我不確定.Net框架中序列化和反序列化的最佳方法。

根據MSDN數據類型摘要 ,沒有位數據類型。 我不知道如何創建這樣的數據類型,或者即使有可能,所以我只剩下將序列化/反序列化為字節/字節數組。

從NTP數據包的頂部給出以下示例:

     0-1         LeapIndicator (LI)      2 bits
     2-4         VersionNumber (VN)      3 bits
     5-7         Mode                    3 bits
     8-15        Stratum                 8 bits

我想編碼為2個字節,以便可以通過套接字發送。

另外,我當前使用int表示枚舉中的位,是否可以使用bits / hex或比int更好的東西? 例如,模式枚舉定義如下:

public enum Mode
{
    /*
     +-------+--------------------------+
     | Value | Meaning                  |
     +-------+--------------------------+
     | 0     | reserved                 |
     | 1     | symmetric active         |
     | 2     | symmetric passive        |
     | 3     | client                   |
     | 4     | server                   |
     | 5     | broadcast                |
     | 6     | NTP control message      |
     | 7     | reserved for private use |
     +-------+--------------------------+
     */

    Resevered = 0,
    SymmetricActive = 1,
    SymmetricPassive = 2,
    Client = 3,
    Server = 4,
    Broadcast = 5,
    ControlMessage = 6,
    PrivateUse = 7
}

旁注:該項目的代碼最終將開源,請記住,如果您回答。 如果您不希望共享該代碼,請說::)將在代碼中放置指向此問題的鏈接。

提前致謝 :)

更新:如果人們想知道NTP數據包結構是什么樣子,直接取自RFC 5905,第18頁

        0                   1                   2                   3
        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |LI | VN  |Mode |    Stratum     |     Poll      |  Precision   |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |                         Root Delay                            |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |                         Root Dispersion                       |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |                          Reference ID                         |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |                                                               |
        +                     Reference Timestamp (64)                  +
        |                                                               |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |                                                               |
        +                      Origin Timestamp (64)                    +
        |                                                               |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |                                                               |
        +                      Receive Timestamp (64)                   +
        |                                                               |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |                                                               |
        +                      Transmit Timestamp (64)                  +
        |                                                               |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |                                                               |
        .                                                               .
        .                    Extension Field 1 (variable)               .
        .                                                               .
        |                                                               |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |                                                               |
        .                                                               .
        .                    Extension Field 2 (variable)               .
        .                                                               .
        |                                                               |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |                          Key Identifier                       |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |                                                               |
        |                            dgst (128)                         |
        |                                                               |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

我認為我根本不會在此處使用枚舉。 我可能會創建一個表示數據包頭的結構,將數據存儲在ushort (16位)中:

public struct NtpHeader
{
    private readonly ushort bits;

    // Creates a header from a portion of a byte array, e.g
    // given a complete packet and the index within it
    public NtpHeader(byte[] data, int index)
    {
        bits = (ushort) (data[index] + (data[index] << 8));
    }

    public NtpHeader(int leapIndicator, int versionNumber,
                     int mode, int stratum)
    {
        // TODO: Validation
        bits = (ushort) (leapIndicator |
                         (versionNumber << 2) |
                         (mode << 5) |
                         (stratum << 8));
    }

    public int LeapIndicator { get { return bits & 3; } }

    public int VersionNumber { get { return (bits >> 2) & 7; } }

    public int Mode { get { return (bits >> 5) & 7; } }

    public int Stratum { get { return bits >> 8; } }
}

不過,您需要檢查一下-目前尚不清楚RFC中真正表示的是哪種比特安排。 如果您的樣本數據包具有預期值,那將使事情變得更加清晰。

僅供參考,.NET中有一個結構代表一點,它是System.Boolean 如Marc所述,協議以偶數字節為單位,因此您可以使用int(每個int持有32位)或以位掩碼樣式使用枚舉。 無論哪種方式,都可以使用System.BitConverter的靜態方法來進行字節數組之間的轉換。

您是否考慮過使用Flags屬性? 它允許您將枚舉類型值視為位而不是整數: http : //msdn.microsoft.com/zh-cn/library/system.flagsattribute.aspx

C#中最小的枚舉類型是字節(其他可用類型在這里http://msdn.microsoft.com/zh-cn/library/sbbt4032.aspx進行了說明)。 定義一個字節類型的枚舉:

enum Name:byte{}

在您的示例中:

public enum Mode:byte
{
    /*
     +-------+--------------------------+
     | Value | Meaning                  |
     +-------+--------------------------+
     | 0     | reserved                 |
     | 1     | symmetric active         |
     | 2     | symmetric passive        |
     | 3     | client                   |
     | 4     | server                   |
     | 5     | broadcast                |
     | 6     | NTP control message      |
     | 7     | reserved for private use |
     +-------+--------------------------+
     */

    Resevered = 0,
    SymmetricActive = 1,
    SymmetricPassive = 2,
    Client = 3,
    Server = 4,
    Broadcast = 5,
    ControlMessage = 6,
    PrivateUse = 7
}

如果希望節省空間但可讀性較低,則可以看到sizeof(LeapIndicator)+ sizeof(VersionNumber)+ sizeof(Mode)= 8位= 1字節。 並且sizeof(Sratum)= 8位= 1個字節。

序列化:要將數據包字段放入結果中,只需將2(左移)乘以適當的位數,然后將其與到目前為止的累積結果相乘即可。

反序列化:要從結果中提取數據包字段,只需使用AND位掩碼,然后除以2(右移)除以適當的位數即可。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM