1. 程式人生 > >【C#】 C#/C++Socket通訊資料轉換

【C#】 C#/C++Socket通訊資料轉換

在實際專案開發中,往往碰到需要高效能的同時又希望帶給客戶舒適體驗的情況。於是C#做GUI前臺。C++做後臺通訊就變成一種完美的結合了。舉例來說就是C++呼叫攝像頭的API然後將流返回到GUI客戶端將攝像頭的內容顯示在GUI上。

   我們都知道C#Socket通訊可以採用兩種方式一種是傳遞byte陣列,另一種是傳遞Xml。在C#和C++進行socket通訊時我們採取更多的是byte陣列的方式。今天主要記錄C#中如何將結構體轉化為位元組陣列。當然裡面使用了C#不安全的指標方式。下面這段程式碼的主要功能是根據傳入的結構體開闢空間然後生成位元組陣列返回。Type=>Byte[]

public static byte[] StructToBytes<T>(T structType)
        {

            int size = Marshal.SizeOf(structType);

            byte[] bytes = new byte[size];

            IntPtr structPtr = Marshal.AllocHGlobal(size);

            Marshal.StructureToPtr(structType, structPtr, false);

            Marshal.Copy(structPtr, bytes, 0, size);

            Marshal.FreeHGlobal(structPtr);

            return bytes;

        }


下面這段程式碼的主要功能是根據傳入的位元組陣列開闢空間然後生成相應的型別。Byte[]=>Type這一段通常用在C#socket伺服器端接收C++傳輸的資料

public T BytesToStruct <T>(byte[] bytes, Type type)
        {
            T obj = default(T);

            int size = Marshal.SizeOf(type);

            if (size > bytes.Length)
            {
                return obj;
            }

            IntPtr structPtr = Marshal.AllocHGlobal(size);

            Marshal.Copy(bytes, 0, structPtr, size);

            obj = (T)Marshal.PtrToStructure(structPtr, type);

            Marshal.FreeHGlobal(structPtr);

            return obj;
        }


 …………………………………………………………………………………………………………………………………………………………………………………………………………

在寫C#TCP通訊程式時,傳送資料時,只能傳送byte陣列,處理起來比較麻煩不說,如果是和VC6.0等寫的程式通訊的話,很多的都是傳送結構體,在VC6.0中可以很方便的把一個char[]陣列轉換為一個結構體,而在C#卻不能直接把byte陣列轉換為結構體,要在C#中傳送結構體,可以按以下方法實現: 1)定義結構體:    //名稱空間    using System.Runtime.InteropServices;

//注意這個屬性不能少    [StructLayoutAttribute(LayoutKind.Sequential,CharSet=CharSet.Ansi,Pack=1)]

    struct TestStruct    {        public int c;        //字串,SizeConst為字串的最大長度        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]        public string str;        //int陣列,SizeConst表示陣列的個數,在轉換成        //byte陣列前必須先初始化陣列,再使用,初始化        //的陣列長度必須和SizeConst一致,例test = new int[6];        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]        public int[] test;    }

2)結構體轉byte陣列:        //// <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;        }3byte陣列轉結構體:        /// <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;        }