• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

C#用socket传输类或结构,以及结构和bytes[]互转

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

最近有一项目,是和另外一家公司合作,需要接收对方发来的结构消息,然后填充好后发回。

 

 

涉及到利用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里面除了基本数据类型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时使用。 。


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap