[英]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.