亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C# > 正文

C#中結構體定義并轉換字節數組詳解

2019-10-29 21:09:12
字體:
來源:轉載
供稿:網友

最近的項目在做socket通信報文解析的時候,用到了結構體與字節數組的轉換;由于客戶端采用C++開發,服務端采用C#開發,所以雙方必須保證各自定義結構體成員類型和長度一致才能保證報文解析的正確性,這一點非常重要。

       首先是結構體定義,一些基本的數據類型,C#與C++都是可以匹配的:

  [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]  public struct Head  {    public ushort proMagic;     //包起始標記:固定0x7e7e    public ushort proPackLen;    //包長度:包頭 + 數據區 + 包尾長度,注意不要超過最大長度限制    public long  proSrcAddr;    //源地址:不使用,填0    public ushort proSrcPort;    //源地址端口:不使用,填0    public long  proDstAddr;    //目的地址:不使用,填0    public ushort proDstPort;    //目的端口:不使用,填0    public ushort proCmdCode;    //命令碼:參見以上命令碼定義    public ushort proVersion;    //版本號:不使用,填1    public char  proSerial;     //報文序號:一條報文實例對應一個序號,不同報文疊加,0-255往復    public ushort proPackSum;    //總包數:當包長超過最大長度限制時,需要拆包,大包拆小包總數,不拆默認1    public ushort proPackId;     //當前包號:對應以上總包數的小包標識,不拆默認0  }

       一、首先是 [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)],這是C#引用非托管的C/C++的DLL的一種定義定義結構體的方式,主要是為了內存中排序,LayoutKind有兩個屬性Sequential和Explicit,Sequential表示順序存儲,結構體內數據在內存中都是順序存放的,CharSet=CharSet.Ansi表示編碼方式。這都是為了使用非托管的指針準備的,這兩點大家記住就可以。

       需要注意的是 Pack = 1 這個特性,它代表了結構體的字節對齊方式,在實際開發中,C++開發環境開始默認是2字節對齊方式 ,拿上面報文包頭結構體為例,char類型在雖然在內存中至占用一個字節,但在結構體轉為字節數組時,系統會自動補齊兩個字節,所以如果C#這面定義為Pack=1,C++默認為2字節對齊的話,雙方結構體會出現長度不一致的情況,相互轉換時必然會發生錯位,所以需要大家都默認1字節對齊的方式,C#定義Pack=1,C++ 添加 #pragma pack 1,保證結構體中字節對齊方式一致。

       二、數組的定義,結構體中每個成員的長度都是需要明確的,因為內存需要根據這個分配空間,而C#結構體中數組是無法進行初始化的,這里我們需要在成員聲明時進行定義;

  /// <summary>  /// 終端信息查詢  /// </summary>  [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]  public struct PackTerminalSearch5001  {    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)]    /// <summary>    /// 終端編號    /// </summary>    public string stationCode;    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]    /// <summary>    /// 回復指令    /// </summary>    public Byte[] order;  }  /// <summary>  /// 終端信息數據  /// </summary>  [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]  public struct PackTerminalSearch3004  {    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)]    /// <summary>    /// 終端編號    /// </summary>    public string stationCode;    /// <summary>    /// 終端IP    /// </summary>    public long terminalIP;    /// <summary>    /// 終端端口    /// </summary>    public ushort terminalPort;    /// <summary>    /// 中心IP    /// </summary>    public long serverIP;    /// <summary>    /// 測站端口    /// </summary>    public ushort serverPort;    /// <summary>    /// 磁盤信息數組    /// </summary>    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]    public PackDiskInfo[] diskInfoArray;  }  /// <summary>  /// 磁盤信息  /// </summary>  [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]  public struct PackDiskInfo  {    /// <summary>    /// 盤符    /// </summary>    public char drive;    /// <summary>    /// 總空間    /// </summary>    public double totalSize;    /// <summary>    /// 可用空間    /// </summary>    public double usableSize;  }


 

        上面的代碼需要注意的是string類型實際為Char[6]長度的數組,實際使用中只能有效的使用前5個字符,因為char[6]最后一位默認/0;

        三、結構體與字節數組的互轉

    PackTerminalSearch5001 info;    info.stationCode = "12345";    info.order = new byte[6] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };    Byte[] recv = StructToBytes(info);    object obj = BytesToStuct(recv, typeof(PackTerminalSearch5001));    PackTerminalSearch5001 info5001 = (PackTerminalSearch5001)obj;    byte[] order = info5001.order;    //// <summary>    /// 結構體轉byte數組    /// </summary>    /// <param name="structObj">要轉換的結構體</param>    /// <returns>轉換后的byte數組</returns>    public static byte[] StructToBytes(object structObj)    {      //得到結構體的大小      int size = Marshal.SizeOf(structObj);      //創建byte數組      byte[] bytes = new byte[size];      //分配結構體大小的內存空間      IntPtr structPtr = Marshal.AllocHGlobal(size);      //將結構體拷到分配好的內存空間      Marshal.StructureToPtr(structObj, structPtr, false);      //從內存空間拷到byte數組      Marshal.Copy(structPtr, bytes, 0, size);      //釋放內存空間      Marshal.FreeHGlobal(structPtr);      //返回byte數組      return bytes;    }    /// <summary>    /// byte數組轉結構體    /// </summary>    /// <param name="bytes">byte數組</param>    /// <param name="type">結構體類型</param>    /// <returns>轉換后的結構體</returns>    public static object BytesToStuct(byte[] bytes, Type type)    {      //得到結構體的大小      int size = Marshal.SizeOf(type);      //byte數組長度小于結構體的大小      if (size > bytes.Length)      {        //返回空        return null;      }      //分配結構體大小的內存空間      IntPtr structPtr = Marshal.AllocHGlobal(size);      //將byte數組拷到分配好的內存空間      Marshal.Copy(bytes, 0, structPtr, size);      //將內存空間轉換為目標結構體      object obj = Marshal.PtrToStructure(structPtr, type);      //釋放內存空間      Marshal.FreeHGlobal(structPtr);      //返回結構體      return obj;    }

盡管在C#中結構與類有著驚人的相似度,但在實際應用中,會常常因為一些特殊之類而錯誤的使用它,下面幾點內容是筆者認為應該注意的:

對于結構

1)可以有方法與屬性
2)是密封的,不能被繼承,或繼承其他結構
3)結構隱式地繼承自System.ValueType
4)結構有默認的無參數構造函數,可以將每個字段初始化為默認值,但這個默認的構造函數不能被替換,即使重載了帶參數的構造函數
5)結構沒有析構函數
6)除了const成員外,結構的字段不能在聲明結構時初始化
7)結構是值類型,在定義時(盡管也使用new運算符)會分配堆??臻g,其值也存儲于堆棧
8)結構主要用于小的數據結構,為了更好的性能,不要使用過于龐大的結構
9)可以像類那樣為結構提供 Close() 或 Dispose() 方法

如果經常做通信方面的程序,結構體是非常有用的(為了更有效地組織數據,建議使用結構體)


注:相關教程知識閱讀請移步到c#教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
在线观看日韩专区| 国产ts人妖一区二区三区| 欧美精品制服第一页| 奇米一区二区三区四区久久| 国产精品视频久久久| 91精品视频一区| 久久天天躁狠狠躁夜夜爽蜜月| 国产一区二区美女视频| 日韩精品中文字| 亚洲图片欧美午夜| 91视频免费网站| 欧美精品激情blacked18| 亚洲精品女av网站| 日韩动漫免费观看电视剧高清| 国产精品福利在线| 最近2019中文免费高清视频观看www99| 亚洲欧洲午夜一线一品| 国产日韩中文在线| 欧美精品少妇videofree| 成人春色激情网| 性视频1819p久久| 91精品久久久久久久久| 亚洲人成网站777色婷婷| 亚洲国产精彩中文乱码av| 色偷偷偷综合中文字幕;dd| 久久久久久久影视| 91精品久久久久久久久久久| 97在线看免费观看视频在线观看| 欧美日韩国产在线| 国产乱肥老妇国产一区二| 欧美一区二区三区精品电影| 精品女厕一区二区三区| 91香蕉亚洲精品| 91精品啪aⅴ在线观看国产| 久久久精品中文字幕| 日韩高清中文字幕| 亚洲最大的免费| 91精品视频在线看| 国产日韩欧美综合| 欧美一级电影在线| 欧美裸体男粗大视频在线观看| 这里只有精品在线观看| 亚洲精品在线视频| 欧美亚洲另类视频| 成人有码视频在线播放| 日韩中文在线不卡| 国产日韩在线观看av| 中文字幕视频一区二区在线有码| 国产丝袜一区二区三区| 免费av在线一区| 久久久在线免费观看| 欧美精品久久久久久久| 日韩免费观看视频| 欧美大片欧美激情性色a∨久久| 国产日韩精品一区二区| 欧美成人免费全部观看天天性色| 日韩成人av在线播放| 久久久av亚洲男天堂| 日本一欧美一欧美一亚洲视频| 国产精品第二页| 国产丝袜精品第一页| 最好看的2019年中文视频| 欧美成人精品不卡视频在线观看| 成人福利网站在线观看11| 夜夜嗨av色一区二区不卡| 欧美精品18videos性欧| 精品国产一区二区三区在线观看| 国产精品偷伦一区二区| 91综合免费在线| 精品一区电影国产| 欧美激情免费在线| 国产精品欧美日韩| www.欧美免费| 色99之美女主播在线视频| 亚洲天堂2020| 国产亚洲成精品久久| 国产日本欧美视频| 国产精品网红直播| 欧美孕妇性xx| 亚洲一区二区久久久久久久| 久久伊人精品一区二区三区| 国产精品自产拍在线观看中文| 精品福利视频导航| 久久色精品视频| 亚洲性69xxxbbb| 中文字幕日韩精品在线观看| 欧美电影免费观看电视剧大全| 欧美激情在线播放| 4p变态网欧美系列| 亚洲精品视频在线播放| 亚洲电影免费观看高清| 亚洲欧美制服第一页| 久久久视频在线| 亚洲国产精品成人va在线观看| 91夜夜揉人人捏人人添红杏| 精品国产乱码久久久久久虫虫漫画| 色哟哟亚洲精品一区二区| 日韩电影在线观看中文字幕| 亚洲色图25p| 国产成人精品av| 久久精品国产亚洲| 在线视频欧美日韩| 日韩av网站导航| 国产精品第一页在线| 国内精品视频一区| 国产精品久久久久久久av大片| 国产亚洲欧美日韩美女| 亚洲在线www| 精品国产区一区二区三区在线观看| 色999日韩欧美国产| 亚洲精品乱码久久久久久金桔影视| 欧美黑人又粗大| 美女视频久久黄| 欧美日韩国产成人在线观看| 精品亚洲男同gayvideo网站| 热久久视久久精品18亚洲精品| 色哟哟网站入口亚洲精品| 91精品国产高清自在线| 国内精品视频在线| 久久国产一区二区三区| 国产日韩欧美综合| 欧美视频一区二区三区…| 国产成人精品一区二区在线| 国产精品欧美激情在线播放| 欧美成人精品激情在线观看| 日韩欧美中文字幕在线播放| 精品久久久久久久久久ntr影视| 久久久久久综合网天天| 国产欧美精品在线播放| 98午夜经典影视| 久久免费在线观看| 欧美大荫蒂xxx| 98精品国产高清在线xxxx天堂| 中文字幕免费精品一区高清| 欧美黑人极品猛少妇色xxxxx| 国产精品无av码在线观看| 在线电影中文日韩| 欧美一区二区色| 国产精品自拍偷拍| 欧美做爰性生交视频| 欧美人与物videos| 一区二区三区动漫| 欧美另类在线观看| 久久激情视频久久| 欧美黑人视频一区| 综合网中文字幕| 国产在线播放91| 91网站在线免费观看| 久久久久久久久综合| 欧美激情日韩图片| 国产亚洲精品va在线观看| 国产91久久婷婷一区二区| 日韩视频在线免费观看| 欧美另类精品xxxx孕妇| 日韩视频亚洲视频| 国产精品私拍pans大尺度在线| 亚洲一区二区免费| 国产亚洲精品一区二区| 中文字幕日韩av电影| 国产欧美精品一区二区| 精品国产精品三级精品av网址| 亚洲精品自拍偷拍| 国产九九精品视频| 亚洲国产精品高清久久久|