I have a record:
Tconnecting = record
var
a: int64;
b: integer;
c: integer;
end;
which I need send to server using UDP protocol
I fill it
packet.a := StrToInt64('0x1234567890');
packet.b := 0;
packet.c := RandomRange(1, 9999999);
and sending it
SetLength(send_data, sizeof(packet));
send_data := RawToBytes(packet, SizeOf(packet));
udp.SendBuffer(make_it_big_endian(send_data)); <-- the question... "network byte order"
or maybe I'm doing something wrong? I need to send "bign endian" packet
pack("N*", int64, int, int); (this is in PHP)
Thanks.
Assuming your code is running in a little-endian OS/Machine (like Windows/Intel), you can just reverse the individual bytes of your packet, for example, include the FMX.Types unit in your uses clause:
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;
What you are actually doing is converting from host byte order to network byte order. All standard sockets libraries provide helper functions to do that.
For example, Winsock offers htons, htonl etc. And in the opposite direction you have ntohs, ntohl etc. If you are using Indy, then the equivalent functions are GStack.HostToNetwork
and GStack.NetworkToHost
.
You should serialize each field into a byte stream, with each field being transformed by the appropriate hton* function. Then you can put the byte stream on the wire.