从字节数组中创建任意数量的对象.Dhcp包C#



我目前正在开发一个公共库,该库将允许您创建一个具有各种选项(如dhcp选项(的dhcp包。创建它时,会创建一个字节数组,您可以通过UdpSocket将其作为有效负载发送。我为此创建了两个类:1。dhcpbacket,2。dhcp选项。到目前为止,使用任何DhcpOptions创建Dhcp数据包的工作已经完成。

现在,我想解析传入的DhcpPackets,它们以字节数组的形式传递回DhcpPacket对象,以便能够读取重要信息,如消息类型或从传递的DhcpOptions(如子网掩码(中读取。DhcpPacket的固定部分(开头(我已经同意了。但现在我使用DhcpOptions失败了,因为它们是可变的。如何从字节数组创建X对象。

Given是一个未给定长度的字节数组

dhcpOptions = pPayload.Skip(240).ToArray();

从这个有效载荷中,我现在想要创建类"的对象;DhcpOption";。每个Dhcp选项都以一个唯一的字节开始,例如0x01=包含子网掩码的DhcpOption。然后跟在一个字节后面,该字节指示DhcpOption的长度,包括以下值。例如,如果DNS服务器通过Dhcp选项进行通信,则长度为0x04,因为IPv4地址是作为值传输的。因此,有效负载中Dhcp选项的总长度为6个字节。但由于所有选项的长度都不相同,我不知道下一个DHCP选项的起点是什么。

从ByteArray创建dhcp选项的示例:

DhcpOption option = new DhcpOption{
optionId = byteArray[0],
optionLength = byteArray[1],
optionValue = byteArray.Skip(2).Take(optionLength).ToArray(),
};

搜索的是类的X对象:

public class DhcpOption
{
/// <summary>
/// Define the DHCP options to be created by name
/// </summary>
public dhcpOptionIds optionId { get; set; } = new dhcpOptionIds();
private byte[] optionIdBytes = new byte[] { };
/// <summary>
/// Define the required length for the optionValue
/// </summary>
public byte[] optionLength { get; set; } = new byte[] { };
/// <summary>
/// Define the value for the option e.g. subnet mask
/// </summary>
public byte[] optionValue { get; set; } = new byte[] { };
/// <summary>
/// Create the DHCP option as byte array. Is then specified as an option in the DhcpPacket.
/// </summary>
/// <returns></returns>
public byte[] buildDhcpOption()
{
object selected = Convert.ChangeType(optionId, optionId.GetTypeCode());
optionIdBytes = new byte[] { Convert.ToByte(selected, null) };
return optionIdBytes.Concat(optionLength).Concat(optionValue).ToArray();
}
}

我想要一个dhcp选项列表,而不是一个纯字节数组。因此,List<DhcpOption>可以用于搜索具有for或foreach的所需Dhcp选项,然后读取该值。

这是GitHub的repo,所以我不必复制代码。

https://github.com/Marschall-dev/DhcpDotNet/blob/main/DhcpDotNet/DhcpDotNet/DhcpPacket.cs

如果您有一个需要遵循的固定协议,我使用的典型方法是BinaryReader/BinaryWriter。

从字节数组创建一个内存流,并将其馈送到binaryReader。如果您有多个不同选项的列表,则每个选项的数据都应该以选项的类型为前缀,还可以选择以长度为前缀。因此,您可以先读取选项的类型,然后使用一个开关来处理每个特定的选项类型。重复此操作,直到读取所有选项。

序列化和反序列化通常应该是相反的,因此您可能希望使用BinaryWriter进行序列化。单元测试非常有用,可以确保您可以在不涉及任何网络连接的情况下序列化和反序列化消息。如果你不需要遵循现有的协议,我建议你使用一个序列化库,比如protobuf.net.

最新更新