软件原来是用DELPHI写的,翻译成C#,服务器端是VC写的,原来的协议比较复杂,我就用DELPHI写了一个非常简单的,用的INDY组件
C#发送结构体,但是有几个问题,发送字符串与BYTE类型的都没有问题,但是发送整数据却不对,另外发送结构体数据应该如何写呢?
上代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using MTWS.Net.SocketClient;namespace MTWS.Net.AppCode
{
    public partial class TestTcp : Form
    {
        public TestTcp()
        {
            InitializeComponent();
        }        struct TMsgHeadInfo
        {
            //[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
            public char MsgCode;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
            public char[] MsgType;
            public byte Sender;
            //public int SendInt;
        }        struct TMsgBody
        {
            public TMsgHeadInfo msghead;    
            public Int32 body;   //这里哪个类型对就DELPHI里的integer?
        }        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;
        }        private void TestTcp_Load(object sender, EventArgs e)
        {
            
        }        private void button1_Click(object sender, EventArgs e)
        {
            int ret;
            TMsgBody msgbody;
            //TMsgHeadInfo msghead;
            TCPClient tcp = new TCPClient();
            string code = "zp";
            string type = "ai";
            //string body = "cc";
            ret = tcp.ConnectServer("127.0.0.1", 3578);
            if (ret == 0)
            {
                MessageBox.Show("连接服务器失败");
                            }
            else
            {
                MessageBox.Show("连接服务器成功");                msgbody.msghead.MsgCode = code.ToCharArray();
                msgbody.msghead.MsgType = type.ToCharArray();
                msgbody.msghead.Sender = 5;
                msgbody.body = 44;// body.ToCharArray();
              
                byte[] msg = StructToBytes(msgbody);
                if (tcp.SendMsg(msg) > 0)
                {
                    MessageBox.Show("发送成功");
                }
                else
                {
                    MessageBox.Show("发送失败");
                }
            }        }
    }
}

解决方案 »

  1.   

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    using MTWS.Net.SocketClient;
     
    namespace MTWS.Net.AppCode
    {
        public partial class TestTcp : Form
        {
            public TestTcp()
            {
                InitializeComponent();
            }
     
            struct TMsgHeadInfo
            {
                [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
                public char[] MsgCode;
                [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
                public char[] MsgType;
                public byte Sender;
            }
     
            struct TMsgBody
            {
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
    public TMsgHeadInfo[] msghead;
                public Int32 body;   //这里哪个类型对就DELPHI里的integer?
            }
     
            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;
            }
     
            private void TestTcp_Load(object sender, EventArgs e)
            {
                 
            }
     
            private void button1_Click(object sender, EventArgs e)
            {
                int ret;
                TMsgBody msgbody;
                //TMsgHeadInfo msghead;
                TCPClient tcp = new TCPClient();
                string code = "zp";
                string type = "ai";
                ret = tcp.ConnectServer("127.0.0.1", 3578);
                if (ret == 0)
                {
                    MessageBox.Show("连接服务器失败");
                     
     
                }
                else
                {
                    MessageBox.Show("连接服务器成功");
     
                    msgbody.msghead[0].MsgCode = code.ToCharArray();
                    msgbody.msghead[0].MsgType = type.ToCharArray();
                    msgbody.msghead[0].Sender = 5;                string code = "zp11";
                    string type = "ai11";
                    msgbody.msghead[1].MsgCode = code.ToCharArray();//这样写,直接提示错误,无法编译
                    msgbody.msghead[1].MsgType = type.ToCharArray();
                    msgbody.msghead[1].Sender = 5;
                   
                    byte[] msg = StructToBytes(msgbody);
                    if (tcp.SendMsg(msg) > 0)
                    {
                        MessageBox.Show("发送成功");
                    }
                    else
                    {
                        MessageBox.Show("发送失败");
                    }
                }
     
            }
        }
    }
      

  2.   

    假如报文里有结构体数据,应该如何写?
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    using MTWS.Net.SocketClient;
     
    namespace MTWS.Net.AppCode
    {
        public partial class TestTcp : Form
        {
            public TestTcp()
            {
                InitializeComponent();
            }
     
            struct TMsgHeadInfo
            {
                [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
                public char[] MsgCode;
                [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
                public char[] MsgType;
                public byte Sender;
            }
     
            struct TMsgBody
            {
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
    public TMsgHeadInfo[] msghead;
                public Int32 body;   //这里哪个类型对就DELPHI里的integer?
            }
     
            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;
            }
     
            private void TestTcp_Load(object sender, EventArgs e)
            {
                 
            }
     
            private void button1_Click(object sender, EventArgs e)
            {
                int ret;
                TMsgBody msgbody;
                //TMsgHeadInfo msghead;
                TCPClient tcp = new TCPClient();
                string code = "zp";
                string type = "ai";
                ret = tcp.ConnectServer("127.0.0.1", 3578);
                if (ret == 0)
                {
                    MessageBox.Show("连接服务器失败");
                     
     
                }
                else
                {
                    MessageBox.Show("连接服务器成功");
     
                    msgbody.msghead[0].MsgCode = code.ToCharArray();
                    msgbody.msghead[0].MsgType = type.ToCharArray();
                    msgbody.msghead[0].Sender = 5;                string code = "zp11";
                    string type = "ai11";
                    msgbody.msghead[1].MsgCode = code.ToCharArray();//这样写,直接提示错误,无法编译
                    msgbody.msghead[1].MsgType = type.ToCharArray();
                    msgbody.msghead[1].Sender = 5;
                   
                    byte[] msg = StructToBytes(msgbody);
                    if (tcp.SendMsg(msg) > 0)
                    {
                        MessageBox.Show("发送成功");
                    }
                    else
                    {
                        MessageBox.Show("发送失败");
                    }
                }
     
            }
        }
    }
      

  3.   

    定义消息协议eg.
    消息头 + 长度  +  数据正文  +  校验位
    1Byte    4Bytes   N Bytes      1Byte无论你 Byte int long string 还是struct 或者class
    全部转换成字节数组  放到数据正文中struct class 序列化
      

  4.   

    BitConverter
    Encoding
    Serilize都是转换的好办法
      

  5.   


    请用BinaryWriter来写数据包
      

  6.   

    给分吧int型错误了应该为Int16反正vb的是Int16  你应该sizeof看一下这样就能确定大小了
      

  7.   

    看好我的问题再回答
    Socket最终发送的都是Byte[],而你结构体里面的这些数据
     msgbody.msghead.MsgCode = code.ToCharArray();
                    msgbody.msghead.MsgType = type.ToCharArray();
                    msgbody.msghead.Sender = 5;
                    msgbody.body = 44;// body.ToCharArray();
    最后也是生成Byte[] 
    你知道结构体在C++内存中他这些数据是怎么存的么。
    让你用BinaryWrite就是这个意思,生成的Byte[]与你的结构体是一样的,只要按顺序写入对应的值。明白?
      

  8.   

    看好我的问题再回答DELPHI里的integer 是4个字节对应C#里就是 int 或int32
    转换后整型数值不对要看DELPHI的integer转换成字节数组,是以左高位位移,还以右高位位移
      

  9.   

     
            public byte[] StructToBytes(object obj)
            {
                int size = Marshal.SizeOf(obj);
                byte[] bytes = new byte[size];
                IntPtr structPtr = Marshal.AllocHGlobal(size); //分配结构体大小的内存空间
                Marshal.StructureToPtr(obj, structPtr, false); //将结构体拷到分配好的内存空间
                Marshal.Copy(structPtr, bytes, 0, size);       //从内存空间拷到byte数组
                Marshal.FreeHGlobal(structPtr);                //释放内存空间
                return bytes;
            }               msgbody.msghead.MsgCode = code.ToCharArray();
                    msgbody.msghead.MsgType = type.ToCharArray();
                    msgbody.msghead.Sender = 5;
                    msgbody.body = 44;// body.ToCharArray();
                    Tools tool = new Tools();
                    byte[] msg = tool.StructToBytes(msgbody); //上面的方法
    这边发的body是44,那么收到的确是738197504咋回事
      

  10.   

    转换后整型数值不对要看DELPHI的integer转换成字节数组,是以左高位位移,还以右高位位移咋看?不明白,给个代码看看
      

  11.   

    struct TMsgHeadInfo
            {
                [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
                public char[] MsgCode;
                [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
                public char[] MsgType;
                public byte Sender;
            }
            struct TMsgBody
            {
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
    public TMsgHeadInfo[] msghead;
                public Int32 body;   //这里哪个类型对就DELPHI里的integer?
            }这2个结构的DELPHI定义和C#一致吗?它们成员定义的顺序是一致的吗?
      

  12.   

    那你可能要考虑delphi中结构对数据的定义是不是指向另一个地址的指针,问题可能出在这里
      

  13.   

    内存布局要完全一致,最不济你当做一个byte数组填充后发送也行
      

  14.   

    问题已解决,加上[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]就可以,谢谢楼上各位