C#用socket傳輸類或結構,以及結構和bytes[]互轉

來源:互聯網
上載者:User

最近有一項目,是和另外一家公司合作,需要接收對方發來的結構訊息,然後填充好後發回。

 

 

涉及到利用socket傳輸和接收struct。

 

一般情況下我們只需要利用C#提供的序列化和還原序列化即可,將class/struct聲明為可序列化的。

 

 

然後利用BinaryFormatter之類的方法進行序列化及還原序列化操作~自己可以Google一下:C#序列化

 

 

 

 

但是假如對方平台為C++或其它非.NET平台,這樣做就不行了。由於不同平台類型之間的差異,

 

所以有不小的麻煩。

 

 

 先附上C++與C#之間的類型對應關係:

 

 

 

 

C++                      輸入輸出                    C#
==================================
char chr[255]              O               StringBuilder
KCA_DIR                     I                         int
LPCSTR                       I                  string
int                              I                    int
LPSTR                        O            StringBuilder
int*                            O               out int
DWORD                      I                   int
DWORD*                    O               out int
BOOL                          I                     bool
Rc_DBMgr                   I                     IntPtr
long*                          O               out long

API與C#的資料類型對應關係表
API資料類型 類型描述 C#類型 API資料類型 類型描述 C#類型
WORD 16位不帶正負號的整數 ushort CHAR 字元 char
LONG 32位不帶正負號的整數 int DWORDLONG 64位長整數 long
DWORD 32位不帶正負號的整數 uint HDC 裝置描述表控制代碼 int
HANDLE 控制代碼,32位整數 int HGDIOBJ GDI物件控點 int
UINT 32位不帶正負號的整數 uint HINSTANCE 執行個體控制代碼 int
BOOL 32位布爾型整數 bool HWM 視窗控制代碼 int
LPSTR 指向字元的32位指標 string HPARAM 32位訊息參數 int
LPCSTR 指向常字元的32位指標 String LPARAM 32位訊息參數 int
BYTE 位元組 byte WPARAM 32位訊息參數 int

Wtypes.h 中的非託管類型

 

 

非託管 C 語言類型

 

 

託管類名

 

 

說明

 

 

HANDLE

 

 

void*

 

 

System.IntPtr

 

 

32 位

 

 

BYTE

 

 

unsigned char

 

 

System.Byte

 

 

8 位

 

 

SHORT

 

 

short

 

 

System.Int16

 

 

16 位

 

 

WORD

 

 

unsigned short

 

 

System.UInt16

 

 

16 位

 

 

INT

 

 

int

 

 

System.Int32

 

 

32 位

 

 

UINT

 

 

unsigned int

 

 

System.UInt32

 

 

32 位

 

 

LONG

 

 

long

 

 

System.Int32

 

 

32 位

 

 

BOOL

 

 

long

 

 

System.Int32

 

 

32 位

 

 

DWORD

 

 

unsigned long

 

 

System.UInt32

 

 

32 位

 

 

ULONG

 

 

unsigned long

 

 

System.UInt32

 

 

32 位

 

 

CHAR

 

 

char

 

 

System.Char

 

 

用 ANSI 修飾。

 

 

LPSTR

 

 

char*

 

 

System.String 或 System.StringBuilder

 

 

用 ANSI 修飾。

 

 

LPCSTR

 

 

Const char*

 

 

System.String 或 System.StringBuilder

 

 

用 ANSI 修飾。

 

 

LPWSTR

 

 

wchar_t*

 

 

System.String 或 System.StringBuilder

 

 

用 Unicode 修飾。

 

 

LPCWSTR

 

 

Const wchar_t*

 

 

System.String 或 System.StringBuilder

 

 

用 Unicode 修飾。

 

 

FLOAT

 

 

Float

 

 

System.Single

 

 

32 位

 

 

DOUBLE

 

 

Double

 

 

System.Double

 

 

64 位元

 

 

 需要注意的是非託管的BOOL在C#中對應System.Int32。而在API調用時直接用bool即可。

 

  

 

 

socket傳輸的是byte[].所以我們需要把struct轉化為byte[]. 有高人為我們提供了如下方法。

 

 

 

//struct轉換為byte[]
static byte[] StructToBytes(object structObj)
{
int size = Marshal.SizeOf(structObj);
IntPtr buffer = Marshal.AllocHGlobal(size);
try
{
Marshal.StructureToPtr(structObj, buffer, false);
byte[] bytes = new byte[size];
Marshal.Copy(buffer, bytes, 0, size);
return bytes;
}
finally
{
Marshal.FreeHGlobal(buffer);
}

}
//byte[]轉換為struct
static object BytesToStruct(byte[] bytes, Type strcutType)
{
int size = Marshal.SizeOf(strcutType);
IntPtr buffer = Marshal.AllocHGlobal(size);
try
{
Marshal.Copy(bytes, 0, buffer, size);
return Marshal.PtrToStructure(buffer, strcutType);
}
finally
{
Marshal.FreeHGlobal(buffer);
}
}

 

 

 

 

一般情況下到此就結束了。但是假如struct裡面除了基礎資料型別 (Elementary Data Type)int,long,byte之外,還有 char*.比如:

 

 

 

 

typedef struct{   char szStatus[924];   char szError[196];   BYTE bEmergent;} CHECK_STATUS_PARAM

為了確保資料轉送和讀取的正確性,應該固定字串的長度。

 

 

此處就涉及到了:字串的封送處理。見:http://msdn.microsoft.com/zh-cn/library/s9ts558h(VS.80).aspx

 

在不同的情況下我們需要採用不同的封送選項。

 

 

結構中使用的字串

 

字串是結構的有效成員;但是,StringBuilder 緩衝區在結構中是無效的。下表顯示當字串資料型別被作為欄位封送時該類型的封送處理選項。MarshalAsAttribute 屬性提供了若干個 UnmanagedType 枚舉值,以便將字串封送到欄位。
枚舉類型  非託管格式的說明

 

 

UnmanagedType.BStr  
具有預設長度和 Unicode 字元的 COM 樣式的 BSTR。

 

UnmanagedType.LPStr  
指向 ANSI 字元的空終止數組的指標。

 

 

UnmanagedType.LPTStr 
指向平台相關的字元的空終止數組的指標。

 

UnmanagedType.LPWStr 
指向 Unicode 字元的空終止數組的指標。

 

 

UnmanagedType.ByValTStr 
定長的字元數組;數組的類型由包含數組的結構的字元集確定。

 

 

  

 

 

項目要求採用ANSI編碼,於是C#對應的stuct為:

 

 

 

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct CHECK_STATUS_PARAM
{

[MarshalAs( UnmanagedType.ByValTStr, SizeConst = 924 )]
public string szStatus;
[MarshalAs( UnmanagedType.ByValTStr, SizeConst = 196 )]
public string szError;
public byte bEmergent;
}

為了保證正確性,使對象的各個成員在非託管記憶體中的精確位置被顯式控制。我們也可以使用FieldOffsetAttribute指示該欄位在類型中的位置。此方法只有在LayoutKind設定為Explicit時使用。 。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.