我想出了如何将我的位打包成一个16位的ushort,我的枚举是1-13,所以它们都应该适合。问题是我知道我可以以比以前更快的速度打开包装,可耻的是我不想发布可怕的代码。任何见识将是有益的。我的Push不是将其推送到字节数组的字符串,因此字符串将分解为单个字节。我的ushort分解为2个字节,float分解为4个字节,依此类推。这是我要完成的工作的图像。
修订后的代码声明2018年11月27日晚上11:47
Enums.cs
public enum PacketFlags
{
None = 0x1,
Nat = 0x2,
Hb = 0x4,
Dat = 0x8,
Dscvr = 0x16,
Status = 0x20,
Conn = 0x40,
Finn = 0x80,
ReliableOrdered = 0x100,
Sequenced = 0x200,
NotFragged = 0x400,
Frag = 0x800,
Fragout = 0x1000,
}
有问题的方法
public void WriteHeader()
{
Count = Ptr;
var flag = Fragmented | Proto | Flag;
var field = (ushort)flag;
Ptr = 0;
Push(field);
Push(_id);
}
public void ReadHeader()
{
Ptr = 0;
var header = PullUShort();
var flags = (PacketFlags)header;
SetFlag(flags);
SetProto(flags);
SetFrag(flags);
_id = PullUShort();
}
private void SetFlag(PacketFlags flags)
{
//Set Flag
if((flags & PacketFlags.None) != 0)
{
Flag = PacketFlags.None;
}
if ((flags & PacketFlags.Nat) != 0)
{
Flag = PacketFlags.Nat;
}
if ((flags & PacketFlags.Hb) != 0)
{
Flag = PacketFlags.Hb;
}
if ((flags & PacketFlags.Dat) != 0)
{
Flag = PacketFlags.Dat;
}
if ((flags & PacketFlags.Dscvr) != 0)
{
Flag = PacketFlags.Dscvr;
}
if ((flags & PacketFlags.Status) != 0)
{
Flag = PacketFlags.Status;
}
if ((flags & PacketFlags.Conn) != 0)
{
Flag = PacketFlags.Conn;
}
if ((flags & PacketFlags.Finn) != 0)
{
Flag = PacketFlags.Finn;
}
}
private void SetProto(PacketFlags flags)
{
if ((flags & PacketFlags.ReliableOrdered) != 0)
{
Proto = PacketFlags.ReliableOrdered;
}
if ((flags & PacketFlags.Sequenced) != 0)
{
Flag = PacketFlags.Sequenced;
}
}
private void SetFrag(PacketFlags flags)
{
if ((flags & PacketFlags.NotFragged) != 0)
{
Flag = PacketFlags.NotFragged;
}
if ((flags & PacketFlags.Frag) != 0)
{
Flag = PacketFlags.Frag;
}
if ((flags & PacketFlags.Fragout) != 0)
{
Flag = PacketFlags.Fragout;
}
}
请注意,我在.Net 3.5上,这是用于网络解决方案的。如果应用程序每秒处理40k +数据包,并且运行该方法的速度慢,则Enum.HasValue将使用反射。我并不是想轻松获得性能。
答案 0 :(得分:4)
您正在尝试使用位位置指定标志。如果只使用这些位上的值,则更容易。
[Flags]
public enum PacketFlags : ushort
{
None = 0x01, // this is the same as 1 << 1 = 1
Nat = 0x02, // this is the same as 1 << 2 = 2
Hb = 0x04, // this is the same as 1 << 3 = 4
Dat = 0x08,
Dscvr = 0x10,
Status = 0x20, // this is the same as 1 << 6 = 32
Conn = 0x40,
Finn = 0x80,
}
首先,“ none”通常被分配为零,但除此之外,让我们假设即使未设置任何标志,您的标志也将始终被置位。
两个,我以十六进制指定了标志值,但这不是必需的。如果愿意,可以使用简单的以10为底的数字。
三,[Flags]
attribute的全部作用就是改变将枚举格式化为字符串时发生的情况。继续尝试。或将一些标志放在一起,然后在其上调用.ToString()
。然后删除该属性,并注意差异。它很方便,但是没有做任何非常重要的事情。
现在,您的问题:
打包就像对它们进行按位或运算一样简单:
var flag = PacketFlags.Nat | PacketFlags.Hb;
现在,当您想要标记的数字表示形式时,可以将其强制转换为ushort
:
var imaNumber = (ushort)flag; // equals 0x06.
您可以看到[Flags
]属性的作用:
var inEnglish = flag.ToString(); // contains: "Nat, Hb"
解包就像将ushort
值强制转换为PacketFlags
一样简单:
var unpacked = (PacketFlags)imaNumber;
然后您可以使用Enum.HasFlags检查是否设置了特定标志。
此答案旨在帮助您朝正确的方向开始。我可以根据需要修改它。看看可以先买到什么。