socket C#與Delphi互傳結構體

摘要:

      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、感謝網上資料的支持,由於大家的無私奉獻,才完成了此功能,在此統一謝過。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章