使用BitArray C#解码IPFIX数据包

时间:2011-04-19 16:18:30

标签: c# udp decode packets

1 个答案:

答案 0 :(得分:1)

你能给我们转储你收到的一个字节数据包吗?将数组传递给下面的代码,它将把它转储到输出窗口。这将有助于我们查看原始数据包。

    private static string PrintByteArray(byte[] bytes){
        return "byte[] bytes = {0x" + BitConverter.ToString(bytes).Replace("-", ", 0x") + "};";
    }

你是否理解@Paul Sasik在解析数据的答案中所说的内容?结构位于他链接的RFC spec中。数据包的前两个字节(16位)将是版本号。我没有阅读规范,但字节可以用两种不同的方式编写,little and big endian。因此,根据规范,前两个字节应该类似于0x00 0x0a0x0a 0x00

修改

不要考虑比特与字节,只是后者是前者的8个集合。

规范说前16位(2字节)是与你拥有的版本号0x000a相匹配的版本号。然后它说接下来的2个字节是整个消息的长度(以字节为单位)(实际上是八位字节,同样的事情)。您的数据为0x04b4,其小数为1204,这正是字节数组的长度。自1970年1月1日以来,下一个字段是一个4字节的字段,用于导出时间(以Unix / Posix时间为单位)。根据{{​​3}} 0x4dae8ff41,303,285,748Wed, 20 Apr 2011 07:49:08 GMT,其中 private static IPFIX ParseMessageHeader(byte[] bytes) { IPFIX ret = new IPFIX(); ret.Version = ToUInt16BigEndian(bytes, 0); ret.Length = ToUInt16BigEndian(bytes, 2); ret.ExportTime = (new DateTime(1970, 1, 1, 0, 0, 0)).AddSeconds(ToUInt32BigEndian(bytes, 4)); ret.SequenceNumber = ToUInt32BigEndian(bytes, 8); ret.ObservationDomainID = ToUInt32BigEndian(bytes, 12); ret.Sets = new List<Set>(); Int32 CurOctet = 16; Set S; while (true) { S = new Set(); S.SetId = ToUInt16BigEndian(bytes, CurOctet); S.Length = ToUInt16BigEndian(bytes, CurOctet + 2); S.data = bytes.Skip(CurOctet).Take(S.Length).ToArray(); ret.Sets.Add(S); CurOctet += S.Length; if (CurOctet >= ret.Length) { break; } } return ret; } //These two functions are from here http://snipplr.com/view/15179/adapt-systembitconverter-to-handle-big-endian-network-byte-ordering-in-order-to-create-number-types-from-bytes-and-viceversa/ //BitConverter.ToUInt16 would parse the results in "little endian" order so 0x000a would actually be parsed as 0x0a00 and give you 2,560 instead of 10. //The spec says that everything should be in "big endian" (also known as "network order" public static UInt16 ToUInt16BigEndian(byte[] value, int startIndex) { return System.BitConverter.ToUInt16(value.Reverse().ToArray(), value.Length - sizeof(UInt16) - startIndex); } public static UInt32 ToUInt32BigEndian(byte[] value, int startIndex) { return System.BitConverter.ToUInt32(value.Reverse().ToArray(), value.Length - sizeof(UInt32) - startIndex); } struct IPFIX { public UInt16 Version; public UInt16 Length; public DateTime ExportTime; public UInt32 SequenceNumber; public UInt32 ObservationDomainID; public List<Set> Sets; } struct Set { public UInt16 SetId; public UInt16 Length; public byte[] data; public SetType SetType { get { if (SetId == 2) return SetType.TemplateSet; if (SetId == 3) return SetType.OptionTemplate; if (SetId > 255) return SetType.DataSet; throw new ArgumentOutOfRangeException("SetId", "SetId not in expected range of 2, 3 or >255"); } } } enum SetType { TemplateSet, OptionTemplate, DataSet }; int。您可以使用以下代码来解析邮件头。希望这会让你继续解析原始数据。

UInt16

要注意的一点是“endian-ness”。 Windows默认情况下将值解析为小端,但此处的所有值都需要根据规范解析为大端。普通的BitConvertor类在这里不起作用,所以上面有两个辅助函数可以根据需要调整它。此外,您会看到我使用UInt32Int16而不是常规的UInt16。这也符合规范。 {{1}}同时包含负数和正数,而{{1}}没有任何概念(尽管我们通常认为它是正数)。