C# 和 C++ 结构体Socket通信

mac2022-06-30  86

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;        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] // 声明一个字符数组,大小为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数据类型类型描述C#类型API数据类型类型描述C#类型WORD16位无符号整数ushortCHAR字符charLONG32位无符号整数intDWORDLONG64位长整数longDWORD32位无符号整数uintHDC设备描述表句柄intHANDLE句柄,32位整数intHGDIOBJGDI对象句柄intUINT32位无符号整数uintHINSTANCE实例句柄intBOOL32位布尔型整数boolHWM窗口句柄intLPSTR指向字符的32位指针stringHPARAM32位消息参数intLPCSTR指向常字符的32位指针StringLPARAM32位消息参数intBYTE字节byteWPARAM32位消息参数int

 

整个结构的字节数是22bytes。

对应的C++结构体是:

typedef struct{     WORD id;                CHAR name[11];    CHAR password[9];}Operator;

3、发送的时候先要把结构转换成字节数组

        using System.Runtime.InteropServices;     

         /// <summary>        /// 将结构转换为字节数组        /// </summary>        /// <param name="obj">结构对象</param>        /// <returns>字节数组</returns>        public byte[] StructToBytes(object obj)        {            //得到结构体的大小            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;

       }

接收的时候需要把字节数组转换成结构

        /// <summary>        /// byte数组转结构        /// </summary>        /// <param name="bytes">byte数组</param>        /// <param name="type">结构类型</param>        /// <returns>转换后的结构</returns>        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","pass")); // 将结构转换成字节数组

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<byte> newRecv = new List<byte>();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();

转载于:https://www.cnblogs.com/hjqxaly/archive/2010/05/31/1748574.html

相关资源:JAVA上百实例源码以及开源项目
最新回复(0)