socket C#与Delphi互传结构体

来源:互联网 发布:appstore淘宝下载不了 编辑:程序博客网 时间:2024/05/22 01:59

摘要:

      Delphi与C#通过SOCKET通信,互传结构体。好处是可以把协议及要传送的内容封装成一个结构体,一次性发送,不需要再做过多的封包的拆包。封包过程通过的做法是把要发送的内容组成字符串,每个子项内容之间用分隔符隔开,以便客户端收到内容后知道如何拆包。拆包过程就把接收到的字符串再按分隔符分解成多项,并按封包时对应的子项赋值给对应的接收者。整个过程很繁琐,并且不同的开发语言对封包拆包操作的实现的支持也不一样,有的语言方便,有些不方便。

那么采用结构体的好处就显而易见了。其一只需要双方都定义好结构体,发送方转成字节发送,接收方按字节接收,再赋值给结构体变量,就完成了通常意义上封包和拆包过程。其二就是容易控制各项的默认值,各种高级语言对结构体的支持越来越到位、方便了。

正文:

1、C#

        [StructLayout(LayoutKind.Sequential)]//注意此处一定要有此语句
        public struct Body
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]//设置字符的长度,当实际长度不足时,会自动填充0
            public string password;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)]//
            public string Tel;
            public int accid;
        }
        
        //转换方法:
        public byte[] StructToBytes<T>(T obj)
        {
            int size = Marshal.SizeOf(obj);
            byte[] bytes = new byte[size]; 
            IntPtr arrPtr = Marshal.UnsafeAddrOfPinnedArrayElement(bytes, 0);
            Marshal.StructureToPtr(obj, arrPtr, true);
            return bytes;
        }

      //发送

                    Body body;
                    body.accid = 123412345;
                    body.password = "567890123456";
                    body.Tel = "13526396605abcdefg";
                    data = StructToBytes<Body>(body);

                    ClientSocket.Send(Data, 0, Data.Length, SocketFlags.None);

2、接收Delphi

procedure TMain_Frm.btn14Click(Sender: TObject);
type
  TBody=Packed Record              //包体定义
    password: array[0..15] of char;     //密码
    Tel      :array[0..23] of char;     //手机号
    accid:  integer;                          //编号
  end;
var
  data, recbuff: TIdBytes;
  Body: TBody;
begin
  IdTCPClient1.Connect('192.163.1.132', 5632);
  SetLength(data, 1)
  data[0] := $F0;
  idtcpclnt1.Socket.Write(data);//服务端接收到后返回一个整数


  IdTCPClient1.Socket.ReadBytes(recbuff, SizeOf(Body)); 
  Move( recbuff[0], Body, Length(recbuff) - 1);
  ShowMessage('密码:' + Body.password + #13 + 'tel:' + Body.Tel + #13 + '数字:' + FloatToStr(Body.accid));
end;

接收完成时,就是各项分解并赋值完成时,省去了拆包过程。

3、缺点

    1、所有内容都必须是能够提前知道长度的;

     2、传输的内容相对简单,太复杂的结构传不了。

结束语:

      1、本文重点在于介绍不同语言间如何传递结构体,并无强调结构体优越之意。

      2、本文举例的结构可传递协议,也是基于本人的刷卡交易模块。由于格式固定、内容统一,才易于实现。

      3、感谢网上资料的支持,由于大家的无私奉献,才完成了此功能,在此统一谢过。

0 0