代码之家  ›  专栏  ›  技术社区  ›  Levon Ravel

按位向后的最佳方法

c#
  •  -2
  • Levon Ravel  · 技术社区  · 6 年前

    enter image description here

    枚举.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;
            }
        }
    

    请注意,我在.NET3.5上,这是一个网络解决方案。枚举.HasValue如果应用程序使用的是第二个按位处理IREK+40D数据包的方法,则它的第二个按位处理IREK。我不是在找轻松我想要的表现。

    1 回复  |  直到 6 年前
        1
  •  4
  •   Amy    6 年前

    您正在尝试使用位位置指定标志。如果只使用这些位上的值,就更容易了。

    [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'通常被赋值为零,但是撇开它不谈,让我们假设您的标志总是有一个位设置,即使没有设置标志。

    [Flags] attribute 是否更改将枚举格式化为字符串时发生的情况。去试试吧。或者一些旗子一起,然后打电话 .ToString() 在上面。然后移除属性,并注意区别。它很方便,但不起任何非常重要的作用。

    现在,回答你的问题:

    打包非常简单,只需将它们按位排序:

    var flag = PacketFlags.Nat | PacketFlags.Hb;
    

    ushort

    var imaNumber = (ushort)flag;  // equals 0x06.
    

    你可以看到 [Flags

    var inEnglish = flag.ToString(); // contains: "Nat, Hb"
    

    拆包就像铸造 PacketFlags :

    var unpacked = (PacketFlags)imaNumber;  
    

    然后可以检查是否使用 Enum.HasFlags .

    这个答案是为了让你从正确的方向开始。我可以根据反馈修改它。先看看你能带到哪里。