如何将记录从主机转换为网络字节顺序(大端)?

时间:2012-11-22 02:47:15

标签: delphi delphi-xe3

我有一个记录:

  Tconnecting = record
  var
    a: int64;
    b: integer;
    c: integer;
  end;

我需要使用UDP协议发送到服务器

我填写

  packet.a := StrToInt64('0x1234567890');
  packet.b := 0;
  packet.c := RandomRange(1, 9999999);

并发送

  SetLength(send_data, sizeof(packet));
  send_data := RawToBytes(packet, SizeOf(packet));
  udp.SendBuffer(make_it_big_endian(send_data)); <-- the question... "network byte order"

或者我做错了什么?我需要发送“bign endian”数据包

pack("N*", int64, int, int); (this is in PHP)

感谢。

2 个答案:

答案 0 :(得分:4)

您实际在做的是从主机字节顺序转换为网络字节顺序。所有标准套接字库都提供辅助函数来执行此操作。

例如,Winsock提供htons,htonl等。在相反的方向,你有ntohs,ntohl等。如果你使用Indy,那么等效函数是GStack.HostToNetworkGStack.NetworkToHost

您应该将每个字段序列化为字节流,每个字段都由相应的hton *函数进行转换。然后你可以将字节流放在线上。

答案 1 :(得分:1)

假设您的代码在小端OS /机器(如Windows / Intel)中运行,您只需反转数据包的各个字节,例如,包括FMX.Types单元在您的使用条款:

type
  Tconnecting = record
    a: int64;
    b: integer;
    c: integer;
  end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Packet, BEPacket: Tconnecting;
begin
  packet.a := $0102030405060708;
  packet.b := $01020304;
  packet.c := $05060708;
  //big endian packet  
  BEPacket := Packet;

  ReverseBytes(@BEPacket.a, SizeOf(BePacket.a));
  ReverseBytes(@BEPacket.b, SizeOf(BePacket.b));
  ReverseBytes(@BEPacket.c, SizeOf(BePacket.c));

  Memo1.Lines.Add(Format('a: %16.16x => %16.16x', [Packet.a, BEPacket.a]));
  Memo1.Lines.Add(Format('b: %8.8x => %8.8x', [Packet.b, BEPacket.b]));
  Memo1.Lines.Add(Format('c: %8.8x => %8.8x', [Packet.c, BEPacket.c]));
end;