Code
2、注意C#与C++数据类型的对应关系
C++与C#的数据类型对应关系表 API数据类型 类型描述 WORD LONG DWORD HANDLE UINT BOOL LPSTR LPCSTR BYTE 16位无符号整数 32位无符号整数 32位无符号整数 句柄,32位整数 32位无符号整数 32位布尔型整数 指向字符的32位指针 指向常字符的32位指针 字节 C#类型 API数据类型 ushort CHAR int uint int uint bool string 类型描述 字符 C#类型 char long DWORDLONG 位长整数 HDC HGDIOBJ HINSTANCE HWM HPARAM 设备描述表句柄 int GDI对象句柄 实例句柄 窗口句柄 32位消息参数 32位消息参数 32位消息参数 int int int int int int String LPARAM byte WPARAM 整个结构的字节数是22bytes。 对应的C++结构体是:
1typedef struct 2
{
3 WORD id; 4 CHAR name[11]; 5 CHAR password[9]; 6}Operator; 7 8
3、发送的时候先要把结构转换成字节数组
1 using System.Runtime.InteropServices; 2 3
///
6 /// 结构对象 7 ///
8 public byte[] StructToBytes(object obj) 9
{
10 //得到结构体的大小
11 int size = Marshal.SizeOf(obj); 12 //创建byte数组
13 byte[] bytes = new byte[size]; 14 //分配结构体大小的内存空间
15 IntPtr structPtr = Marshal.AllocHGlobal(size); 16 //将结构体拷到分配好的内存空间
17 Marshal.StructureToPtr(obj, structPtr, false); 18 //从内存空间拷到byte数组
19 Marshal.Copy(structPtr, bytes, 0, size); 20 //释放内存空间
21 Marshal.FreeHGlobal(structPtr); 22 //返回byte数组 23 return bytes; 24
25 } 26 27
接收的时候需要把字节数组转换成结构
1
/// 2 /// byte数组转结构 3 ///
4 /// byte数组 5 /// 结构类型 6 ///
7 public object BytesToStruct(byte[] bytes, Type type) 8
{
9 //得到结构的大小
10 int size = Marshal.SizeOf(type); 11 Log(size.ToString(), 1); 12 //byte数组长度小于结构的大小 13 if (size > bytes.Length)
14 {
15 //返回空 16 return null; 17 }
18 //分配结构大小的内存空间
19 IntPtr structPtr = Marshal.AllocHGlobal(size); 20 //将byte数组拷到分配好的内存空间
21 Marshal.Copy(bytes, 0, structPtr, size); 22 //将内存空间转换为目标结构
23 object obj = Marshal.PtrToStructure(structPtr, type); 24 //释放内存空间
25 Marshal.FreeHGlobal(structPtr); 26 //返回结构 27 return obj; 28 } 29
4、实际操作:
1using System.Collections;
2using System.Collections.Generic; 3using System.Net;
4using System.Net.Sockets; 5
6byte[] Message = StructToBytes(new Operator(\"user\",\"pass\")); // 将结构转换成字节数组 7
8TcpClient socket = new TcpClient(); 9
10socket.Connect(ip,port); 11
12NetworkStream ns = Socket.GetStream(); 13
14ns.Write(Message,0,Message.Length); // 发送 15
16byte[] Recv = new byte[1024]; // 缓冲 17
18int NumberOfRecv = 0; 19
20IList { { 24do 26// 接收响应 27NumberOfRecv = ns.Read(Recv, 0, Recv.Length); 28for (int i = 0; i < NumberOfRecv; i++) 29newRecv.Add(Recv[i]); 30} 31while (ns.DataAvailable); 32byte[] resultRecv = new byte[newRecv.Count]; 33newRecv.CopyTo(resultRecv, 0); 34 35Operator MyOper = new Operator(); 36 37MyOper = (Operator)BytesToStruct(resultRecv, MyOper.GetType()); // 将字节数组转换成结构 38 在这里取值的时候可能会出现只能取到一个字段,剩余的取不到的问题,怎么回事我也搞不懂,反正我的解决办法就是按照字节的顺序从resultRecv里分别取出对应的字段的字节数组,然后解码,例如: Operator.name是11个字节,最后一位是0,Operator.id是2个字节,那么从第3位到第12位的字节就是Operator.name的内容,取出另存为一个数组MyOperName,Encoding.Default.GetString(MyOperName)就是MyOper.name的内容。 1socket.Close(); 2 3ns.Close(); 4 Tag标签: c#,c++,结构体,socket C#和C++结构体Socket通信 最近在用C#做一个项目的时候,Socket发送消息的时候遇到了服务端需要接收C++结构体的二进制数据流,这个时候就需要用C#仿照C++的结构体做出一个结构来,然后将其转换成二进制流进行发送,之后将响应消息的二进制数据流转换成C#结构。 1、仿照C++结构体写出C#的结构来 using System.Runtime.InteropServices; [Serializable] // 指示可序列化 [StructLayout(LayoutKind.Sequential, Pack = 1)] // 按1字节对齐 public struct Operator { public ushort id; // 声明一个字符数组,大小为11 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] public char[] name; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 9)] public char[] pass; public Operator(string user, string pass) // 初始化 { this.id = 10000; this.name = user.PadRight(11, '\\0').ToCharArray(); this.pass = pass.PadRight(9, '\\0').ToCharArray(); } } 2、注意C#与C++数据类型的对应关系 C++与C#的数据类型对应关系表 API数据类型 WORD CHAR LONG 类型描述 C#类型 16位无符号整数 字符 ushort char int 32位无符号整数 DWORD LONG 位长整数 DWORD HDC long uint int int int 32位无符号整数 设备描述表句柄 句柄,32位整数 GDI对象句柄 HANDLE HGDIOBJ UINT 32位无符号整数 实例句柄 uint int bool int HINSTANCE BOOL HWM LPSTR 32位布尔型整数 窗口句柄 指向字符的32位指针 string 32位消息参数 int String HPARAM LPCSTR 指向常字符的32位指针 32位消息参数 字节 int LPARAM BYTE byte int WPARAM 32位消息参数 整个结构的字节数是22bytes。 对应的C++结构体是: typedef struct { WORD id; CHAR name[11]; CHAR password[9]; }Operator; 3、发送的时候先要把结构转换成字节数组 using System.Runtime.InteropServices; /// /// 将结构转换为字节数组 /// /// 结构对象 /// //得到结构体的大小 int size = Marshal.SizeOf(obj); //创建byte数组 byte[] bytes = new byte[size]; //分配结构体大小的内存空间 IntPtr structPtr = Marshal.AllocHGlobal(size); //将结构体拷到分配好的内存空间 Marshal.StructureToPtr(obj, structPtr, false); //从内存空间拷到byte数组 Marshal.Copy(structPtr, bytes, 0, size); //释放内存空间 Marshal.FreeHGlobal(structPtr); //返回byte数组 return bytes; } 接收的时候需要把字节数组转换成结构 /// /// byte数组 /// 结构类型 // public object BytesToStruct(byte[] bytes, Type type) { //得到结构的大小 int size = Marshal.SizeOf(type); Log(size.ToString(), 1); //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; } 4、实际操作: using System.Collections; using System.Collections.Generic; using System.Net; using System.Net.Sockets; byte[] Message = StructToBytes(new Operator(\"user\// 将结构转换成字节数组 TcpClient socket = new TcpClient(); socket.Connect(ip,port); NetworkStream ns = Socket.GetStream(); ns.Write(Message,0,Message.Length); // 发送 byte[] Recv = new byte[1024]; // 缓冲 int NumberOfRecv = 0; IList ns.ReadTimeout = 3000; try { do { // 接收响应 NumberOfRecv = ns.Read(Recv, 0, Recv.Length); for (int i = 0; i < NumberOfRecv; i++) newRecv.Add(Recv[i]); } while (ns.DataAvailable); byte[] resultRecv = new byte[newRecv.Count]; newRecv.CopyTo(resultRecv, 0); Operator MyOper = new Operator(); MyOper = (Operator)BytesToStruct(resultRecv, MyOper.GetType()); // 将字节数组转换成结构 在这里取值的时候可能会出现只能取到一个字段,剩余的取不到的问题,怎么回事我也搞不懂,反正我的解决办法就是按照字节的顺序从resultRecv里分别取出对应的字段的字节数组,然后解码,例如: Operator.name是11个字节,最后一位是0,Operator.id是2个字节,那么从第3位到第12位的字节就是Operator.name的内容,取出另存为一个数组MyOperName,Encoding.Default.GetString(MyOperName)就是MyOper.name的内容。 socket.Close(); ns.Close(); 另外一种方法:用不安全的C#代码来实现,我贴个例子给你,我也想知道有没有办法不用unsafe code来得到结构的字节数组。 using System; using System.Collections.Generic; using System.Text; namespace ConsoleApplication1 { struct Test { public int x, y; } class Program { unsafe static byte[] GetStructBytes(Test t) { int n = sizeof(Test); byte* p = (byte *)&t; byte[] r = new byte[n]; for (int i = 0; i < n; i++) r[i] = p[i]; return r; } static void PrintByteArray(byte[] arr) { Console.Write(\"Bytes : \"); for (int i = 0; i < arr.Length; i++) Console.Write(\"{0:X} \ } static void Main(string[] args) { Test t = new Test(); t.x = 0x11223344; t.y = 0x22334455; byte[] arr = GetStructBytes(t); PrintByteArray(arr); Console.ReadKey(); } } } 通过SOCKET传输C++结构体,传给C#程序,在C#程序中接到228个byte,但C#结构体却有232个byte,各位看看是不是我的C#结构体与C++的结构体没对应上呢? C++结构体: typedef struct { int station; int chanal; int mineid; int positionid; int nodeflag; int nodetype; float alarmupperlimit; float alarmlowerlimit; float poweron; float poweroff; bool deleted; char nodememo[50]; int flag; COleDateTime designtime; char Control[20]; char KDControl[20]; char GZControl[20]; char BSFj[20]; char BSControl[20]; char EJControl[20]; }NODE; C#结构体: struct NODE { int station; int chanal; int mineid; int positionid; int nodeflag; int nodetype; float alarmupperlimit; float alarmlowerlimit; float poweron; float poweroff; bool deleted; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 50)] char[] nodememo; int flag; DateTime designtime; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] char[] Control; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] char[] KDControl; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] char[] GZControl; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] char[] BSFj; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] char[] BSControl; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] char[] EJControl; } C++中COleDateTime 应该也是个结构体,你直接用DateTime 代替似乎不妥。 天啊,楼主你麻烦了,MSDN上说,COleDateTime 对应的是tagVARIANT类型,这个类型是超级麻烦的类型 C#调用c++Dll结构体数组指针的问题 收藏 C#调用c++dll文件是一件很麻烦的事情,首先面临的是数据类型转换的问题,相信经常做c#开发的都和我一样把学校的那点c++底子都忘光了吧(语言特性类)。 网上有一大堆得转换对应表,也有一大堆的转换实例,但是都没有强调一个更重要的问题,就是c#数据类型和c++数据类型占内存长度的对应关系。 如果dll文件中只包含一些基础类型,那这个问题可能可以被忽略,但是如果是组合类型(这个叫法也许不妥),如结构体、类类型等,在其中的成员变量的长度的申明正确与否将决定你对dll文件调用的成败。 如有以下代码,其实不是dll文件的源码,而是厂商给的c++例子代码 c++中的结构体申明 view plaincopy to clipboardprint? typedef struct { unsigned char Port; unsigned long Id; unsigned char Ctrl; unsigned char pData[8]; }HSCAN_MSG; typedef struct { unsigned char Port; unsigned long Id; unsigned char Ctrl; unsigned char pData[8]; }HSCAN_MSG; c++中的函数申明(一个c++程序引用另一个c++的dll文件) view plaincopy to clipboardprint? extern \"C\" int _stdcall HSCAN_SendCANMessage(unsigned char nDevice,unsigned char nPort,HSCAN_MSG *msg,int nLength); extern \"C\" int _stdcall HSCAN_SendCANMessage(unsigned char nDevice,unsigned char nPort,HSCAN_MSG *msg,int nLength); c++中的调用: view plaincopy to clipboardprint? .... HSCAN_MSG msg[100]; ..... HSCAN_SendCANMessage(m_nDevice,m_nPort,msg,nFrames); .... HSCAN_MSG msg[100]; ..... HSCAN_SendCANMessage(m_nDevice,m_nPort,msg,nFrames); 由上述代码可见,msg是个结构体的数组。 下面是我的c#的代码 c#结构体申明:(申明成) view plaincopy to clipboardprint? [StructLayout(LayoutKind.Sequential)] public struct HSCAN_MSG { // UnmanagedType.ByValArray, [MarshalAs(UnmanagedType.U1)]这个非常重要,就是申明对应类型和长度的 [MarshalAs(UnmanagedType.U1)] public byte Port; [MarshalAs(UnmanagedType.U4)] public uint nId; [MarshalAs(UnmanagedType.U1)] public byte nCtrl; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] pData; }; [StructLayout(LayoutKind.Sequential)] public struct HSCAN_MSG { // UnmanagedType.ByValArray, [MarshalAs(UnmanagedType.U1)]这个非常重要,就是申明对应类型和长度的 [MarshalAs(UnmanagedType.U1)] public byte Port; [MarshalAs(UnmanagedType.U4)] public uint nId; [MarshalAs(UnmanagedType.U1)] public byte nCtrl; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] pData; }; c#函数申明 view plaincopy to clipboardprint? [DllImport(\"HS2106API.dll\")] public static extern int HSCAN_SendCANMessage( byte nDevice, byte nPort, HSCAN_MSG[] pMsg, int nLength); [DllImport(\"HS2106API.dll\")] public static extern int HSCAN_SendCANMessage( byte nDevice, byte nPort, HSCAN_MSG[] pMsg, int nLength); C#函数调用 view plaincopy to clipboardprint? HSCAN_MSG[] msg = new HSCAN_MSG[1]; //发送缓冲区大小可根据需要设置; for (int yy = 0; yy < msg.Length; yy++) { msg[yy] = new HSCAN_MSG(); } //...结构体中的成员的实例化略 HSCAN_SendCANMessage(0x0, 0x0, msg, 1) HSCAN_MSG[] msg = new HSCAN_MSG[1]; //发送缓冲区大小可根据需要设置; for (int yy = 0; yy < msg.Length; yy++) { msg[yy] = new HSCAN_MSG(); } //...结构体中的成员的实例化略 HSCAN_SendCANMessage(0x0, 0x0, msg, 1) 那些只能用指针不能用结构体和类的地方 c++中的结构体申明 view plaincopy to clipboardprint? typedef struct { unsigned char Port; unsigned long Id; unsigned char Ctrl; unsigned char pData[8]; }HSCAN_MSG; typedef struct { unsigned char Port; unsigned long Id; unsigned char Ctrl; unsigned char pData[8]; }HSCAN_MSG; c++中的函数申明(一个c++程序引用另一个c++的dll文件) view plaincopy to clipboardprint? extern \"C\" int _stdcall HSCAN_SendCANMessage(unsigned char nDevice,unsigned char nPort,HSCAN_MSG *msg,int nLength); extern \"C\" int _stdcall HSCAN_SendCANMessage(unsigned char nDevice,unsigned char nPort,HSCAN_MSG *msg,int nLength); c#中的结构体申明: view plaincopy to clipboardprint? [StructLayout(LayoutKind.Sequential)] public struct HSCAN_MSG { [MarshalAs(UnmanagedType.U1)] public byte Port; /// /// 节点标识,nEFF=1 时(扩展帧),为29 位nEFF=0(标准帧)时,为11 位; /// [MarshalAs(UnmanagedType.U4)] public uint nId; [MarshalAs(UnmanagedType.U1)] public byte nCtrl; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] pData; }; [StructLayout(LayoutKind.Sequential)] public struct HSCAN_MSG { [MarshalAs(UnmanagedType.U1)] public byte Port; /// /// 节点标识,nEFF=1 时(扩展帧),为29 位nEFF=0(标准帧)时,为11 位; /// [MarshalAs(UnmanagedType.U4)] public uint nId; [MarshalAs(UnmanagedType.U1)] public byte nCtrl; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] pData; }; c#函数的调用:包含使用指针IntPtr替代结构体数组和读取IntPtr的方法 view plaincopy to clipboardprint? HSCAN_MSG[] msg1 = new HSCAN_MSG[10]; for (int i = 0; i < msg1.Length; i++) { msg1[i] = new HSCAN_MSG(); msg1[i].pData = new byte[8]; } IntPtr[] ptArray = new IntPtr[1]; ptArray[0] = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(HSCAN_MSG)) * 10); IntPtr pt = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(HSCAN_MSG))); Marshal.Copy(ptArray, 0, pt, 1); int count = HSCAN_ReadCANMessage(0x0, 0,pt, 10); textBoxStatus.Text += \"\\r\\n\" + \"读取0口:\" + count.ToString() + \"帧数据\"; for (int j = 0; j < 10; j++) { msg1[j] = (HSCAN_MSG)Marshal.PtrToStructure((IntPtr)((UInt32)pt+ j * Marshal.SizeOf(typeof(HSCAN_MSG))) , typeof(HSCAN_MSG)); textBoxStatus.Text += \"\\r\\n收到0口\" + Convert.ToByte(msg1[j].pData[0]).ToString() + \"|\" + Convert.ToByte(msg1[j].pData[1]).ToString() + \"|\" + Convert.ToByte(msg1[j].pData[2]).ToString() + \"|\" + Convert.ToByte(msg1[j].pData[3]).ToString() + \"|\" + Convert.ToByte(msg1[j].pData[4]).ToString() + \"|\" + Convert.ToByte(msg1[j].pData[5]).ToString() + \"|\" + Convert.ToByte(msg1[j].pData[6]).ToString() + \"|\" + Convert.ToByte(msg1[j].pData[7]).ToString(); } HSCAN_MSG[] msg1 = new HSCAN_MSG[10]; for (int i = 0; i < msg1.Length; i++) { msg1[i] = new HSCAN_MSG(); msg1[i].pData = new byte[8]; } IntPtr[] ptArray = new IntPtr[1]; ptArray[0] = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(HSCAN_MSG)) * 10); IntPtr pt = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(HSCAN_MSG))); Marshal.Copy(ptArray, 0, pt, 1); int count = HSCAN_ReadCANMessage(0x0, 0,pt, 10); textBoxStatus.Text += \"\\r\\n\" + \"读取0口:\" + count.ToString() + \"帧数据\"; for (int j = 0; j < 10; j++) { msg1[j] = (HSCAN_MSG)Marshal.PtrToStructure((IntPtr)((UInt32)pt+ j * Marshal.SizeOf(typeof(HSCAN_MSG))) , typeof(HSCAN_MSG)); textBoxStatus.Text += \"\\r\\n收到0口\" + Convert.ToByte(msg1[j].pData[0]).ToString() + \"|\" + Convert.ToByte(msg1[j].pData[1]).ToString() + \"|\" + Convert.ToByte(msg1[j].pData[2]).ToString() + \"|\" + Convert.ToByte(msg1[j].pData[3]).ToString() + \"|\" + Convert.ToByte(msg1[j].pData[4]).ToString() + \"|\" + Convert.ToByte(msg1[j].pData[5]).ToString() + \"|\" + Convert.ToByte(msg1[j].pData[6]).ToString() + \"|\" + Convert.ToByte(msg1[j].pData[7]).ToString(); } 本文来自CSDN博客,转载请标明出处: http://blog.csdn.net/jadeflute/archive/2010/06/21/5684687.aspx C#解析结构体指针浅析 转 这里介绍在C#解析结构体指针前,必须知道结构体是如何定义的,定义完结构体后,就可将接收到C#解析结构体指针转换为定义的结构体对象。 C#语言有很多值得学习的地方,这里我们主要介绍C#解析结构体指针,包括介绍也可将结构体赋值后封送到非托管内存。等方面。 在C#解析结构体指针前,必须知道结构体是如何定义的。 [StructLayout(LayoutKind.Sequential)] public struct VGAStat { public int ChannelNum; //通道数量 [MarshalAs(UnmanagedType.ByValArray, SizeConst = )] public char[] Version; //版本信息 public uint CPUUsage; //CPU占用 public bool WorkStatusOk; //工作状态 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public tagCheckArg[] ChannelStatistic; //通道信息 } 定义完结构体后,就可将接收到C#解析结构体指针转换为定义的结构体对象。 VGAStat entries = (VGAStat)Marshal.PtrToStructure(iptr, typeof(VGAStat)); //iptr为接收到的非托管的结构体指针。 反之,也可将结构体赋值后封送到非托管内存。 假如vga为定义后实例化并赋值了的结构体。 IntPtr intptr = Marshal.AllocHGlobal(Marshal.SizeOf(vga)); Marshal.StructureToPtr(vga, intptr, true); //在此发送intptr指针给目的方 Marshal.FreeHGlobal(intptr); //释放分配的非托管内存。 【原创】C#与C++通过socket传送结构体 C#服务端: 1using System; 2using System.Net.Sockets; 3using System.Net; 4using System.IO; 5using System.Diagnostics; 6using System.Threading; 7using System.Runtime.InteropServices; 8 9 1011 12 13[StructLayout(LayoutKind.Sequential, Pack = 1)] 14 public struct PaketHead 15 { 16 public UInt32 OPCode; 17 public byte DiskFlag; 18 public long DiskSize; 19 public long OPOffSet; 20 public long OPByteCount; 21 22 [MarshalAs(UnmanagedType.ByValArray, SizeConst = )] 23 public byte[] Authentic; 24 public byte Encrypt; 25 public byte Ver; 26 [MarshalAs(UnmanagedType.ByValArray, SizeConst = )] 27 public byte[] AddIn; 28 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] 29 public byte[] Reserve; 30 public byte Zero; 31 public int SizeOfHead; 32 } 33 34 protected byte[] Struct2Bytes { 36 int size = Marshal.SizeOf(obj); 37 byte[] bytes = new byte[size]; 38 IntPtr arrPtr = Marshal.UnsafeAddrOfPinnedArrayElement(bytes, 0); 39 Marshal.StructureToPtr(obj, arrPtr, true); 40 return bytes; 41 } 42 43 protected T Bytes2Struct { 45 IntPtr arrPtr = Marshal.UnsafeAddrOfPinnedArrayElement(bytes, 0); 46 return (T)Marshal.PtrToStructure(arrPtr, typeof(T)); 47 } 48 49 protected void ReadPacketHead(BinaryReader ClientReader, BinaryWriter ClientWriter) 50 { 51 byte[] test = null; 52 test = ClientReader.ReadBytes(180); 53 54 PaketHead Paket = Bytes2Struct 56 Console.WriteLine(Paket.OPCode); 57 Console.WriteLine(Paket.DiskFlag); 58 Console.WriteLine(Paket.DiskSize); 59 Console.WriteLine(Paket.OPOffSet); 60 Console.WriteLine(Paket.OPByteCount); 61 Console.WriteLine(System.Text.Encoding.ASCII.GetString(Paket.Authentic)); 62 Console.WriteLine(Paket.Encrypt); 63 Console.WriteLine(Paket.Ver); Console.WriteLine(System.Text.Encoding.ASCII.GetString(Paket.AddIn)); 65 Console.WriteLine(System.Text.Encoding.ASCII.GetString(Paket.Reserve)); 66 Console.WriteLine(Paket.Zero); 67 Console.WriteLine(Paket.SizeOfHead); 68 ///////////////////////////////// 69 test = Struct2Bytes C++ Client: 1#include 2#pragma comment( lib, \"ws2_32.lib\" ) 3 4#pragma pack(push, 1)//取消内存大小自动对齐 5 6typedef struct _PaketHead2 7 8 9 10 11 12 { UINT OPCode;///////////// UCHAR DiskFlag;////////// __int DiskSize;//////// __int OPOffSet;//////// __int OPByteCount;///// 13 UCHAR Authentic[];// 14 15 16 17 UCHAR Encrypt;//////// UCHAR Ver;//////////// UCHAR AddIn[];////// UCHAR Reserve[16];//// 18 19 UCHAR Zero;/////////// UINT SizeOfHead;///////// 20}PaketHead2,*pPaketHead2; 21 22#pragma pack(pop) 23 24//template 25//void ConvertToByteArray(T arg,unsigned char * Buffer) 26//{ 27// for (int i=0;i 30// Buffer[i] = (arg& (0xff << offset)) >> offset; 31// } 32//} 33// 34//template 35//T ConvertBytesTo(byte *buf) 36//{ 37// T ret = 0x0; 38// for (int i=0;i 43// return (ret); 44//} 45 46int ConnTest() 47{ 48 SOCKET mySocket; 49 WORD wVersionRequested; 50 WSADATA wsaData; 51 int err; 52 53 wVersionRequested = MAKEWORD( 2, 2 ); 54 55 WSAStartup( wVersionRequested, &wsaData ); 56 57 try 58 { 59 err = WSAStartup( wVersionRequested, &wsaData ); 60 if ( err != 0 ) { 61 printf(\"Couldn't find a WinSock DLL\\n\"); 62 return 1; 63 } 65 if ( LOBYTE( wsaData.wVersion ) != 2 || 66 HIBYTE( wsaData.wVersion ) != 2 ) 67 { 68 printf(\"Couldn't find the right version for WinSock 2.2\\n\"); 69 WSACleanup( ); 70 return 1; 71 } 72 73 SOCKADDR_IN ServerAddr; 74 75 mySocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 76 ServerAddr.sin_family = AF_INET; 77 ServerAddr.sin_port = htons(8021); 78 ServerAddr.sin_addr.s_addr = inet_addr(\"192.168.0.5\"); 79 80 81 if (connect(mySocket, (SOCKADDR *) &ServerAddr, sizeof(ServerAddr))) 82 { 83 int error_code = WSAGetLastError(); 84 printf(\"Error connecting socket: %d\\n\ 85 return 1; 86 } 87 88 90 PaketHead2 testhead2; 91 92 memset(&testhead2,0x00,sizeof(PaketHead2)); 93 94 testhead2.DiskFlag = 0x1; 95 testhead2.OPCode = 9856; 96 testhead2.DiskSize = 754612; 97 testhead2.OPOffSet = 983217; 98 testhead2.OPByteCount = 852311; 99 100 memcpy(testhead2.Authentic,\"9876543210ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567abcdefghij1234567\\0\ 101 memcpy(testhead2.AddIn,\"9876543210ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567abcdefghij1234567\\0\ ///////// 102 memcpy(testhead2.Reserve,\"abcdefghij12345\\0\103 104 testhead2.Encrypt = 0x2; 105 testhead2.Ver = 0x4; 106 testhead2.Zero = 0x0; 107 testhead2.SizeOfHead = sizeof(PaketHead2); 108 109 send(mySocket,(char*)(&testhead2),sizeof(PaketHead2),NULL); 110 111 memset(&testhead2,0x00,sizeof(PaketHead2)); 112 recv(mySocket,(char*)(&testhead2),sizeof(PaketHead2),NULL); 113 114 /*testhead2.Authentic[63] = 0; 115 testhead2.AddIn[63] = 0; 116 testhead2.Reserve[15] = 0;*/ 117 118 printf(\"%d\\n\119 printf(\"%d\\n\120 121 printf(\"%ld\\n\122 printf(\"%ld\\n\123 printf(\"%ld\\n\124 125 printf(\"%s\\n\126 printf(\"%d\\n\127 printf(\"%d\\n\128 129 printf(\"%s\\n\130 printf(\"%s\\n\ 131 132 printf(\"%d\\n\133 134 printf(\"%d\\n\135 ////////////////////////////////////////////////// 136 closesocket(mySocket); 137 WSACleanup( ); 138 } 139 catch(140 { ) 141 printf(\"Error!\\n\"); 142 } 143} C#结构体指针的定义及使用详解 http://developer.51cto.com/ 2009-08-13 15:41 dwwwing 博客园 我要评论() C#结构体指针的定义及使用详解主要向你讲述了C#结构体指针是如何定义的,如何实现的。 在解析C#结构体指针前,必须知道C#结构体是如何定义的。在c#中同样定义该结构体。 C#结构体指针之C#结构体的定义: [StructLayout(LayoutKind.Sequential)] public struct VGAStat { public int ChannelNum;//通道数量 [MarshalAs(UnmanagedType.ByValArray, SizeConst = )] public char[] Version;//版本信息 public uint CPUUsage;//CPU占用 public bool WorkStatusOk; //工作状态 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public tagCheckArg[] ChannelStatistic;//通道信息 } 定义完结构体后,就可将接收到的C#结构体指针转换为定义的结构体对象。 VGAStat entries = (VGAStat)Marshal.PtrToStructure(iptr, typeof(VGAStat)); //iptr为接收到的非托管的结构体指针。 反之,也可将结构体赋值后封送到非托管内存。 假如vga为定义后实例化并赋值了的结构体。 IntPtr intptr = Marshal.AllocHGlobal(Marshal.SizeOf(vga)); Marshal.StructureToPtr(vga, intptr, true); //在此发送intptr指针给目的方 Marshal.FreeHGlobal(intptr);//释放分配的非托管内存。 C#结构体指针的定义及使用的相关内容那个就向你介绍到这里,希望对你了解和学习C#结构体指针有所帮助。 C#结构体和字节数组的转换 在写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数组: //// /// 结构体转byte数组 /// /// 要转换的结构体 /// 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; } (3)byte数组转结构体: /// /// byte数组转结构体 /// /// byte数组 /// 结构体类型 /// 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; }
因篇幅问题不能全部显示,请点此查看更多更全内容