0

I've checked and when I convert the ints to hexadecimal they become 4C52 en 524C000000000000 respectively, so it looks as though the bytes are reversed.

The client runs on Delphi XE7 for android and the server runs on Delphi 2007.

How can I fix this?

Push code of client: Client.IOHandler.Write(19538);

Pull code of server: AContext.Connection.IOHandler.ReadInt64; //receives 5930114809340100608

RRUZ
  • 134,889
  • 20
  • 356
  • 483
Friso
  • 2,328
  • 9
  • 36
  • 72

2 Answers2

8

You are not taking endian or byte size into account.

The integer overloads of TIdIOHandler.Write() accept a numeric value in host byte order, which may be either little-endian or big-endian depending on the platform, and will convert them for transmission to network byte order by default, which is big endian. The integer TIdIOHandler.Read...() methods expect numeric values to arrive in network byte order by default, and will convert them to host by order by default. So, if you are using Indy on both sides, you do not have to worry about this detail, since the endian of the reads/writes would be consistent regardless of which platform is on either end.

The TIdIOHandler.Write() numeric overloads, and the TIdIOHandler.Read...() numeric methods, all have an optional Convert parameter that is True by default. If you set this to False instead, values will be sent/read in host byte order instead of network byte order.

What is more important is that you are reading an Int64, but you are not sending an Int64. There are multiple overloads for TIdIOHandler.Write() for the various integer types, and an untyped 19538 constant would never resolve to Int64 with such overloads present. So you need to use a type-cast to tell the compiler to use the Int64 overload:

Client.IOHandler.Write(Int64(19538)); 

Or use a variable:

var
  Value: Int64;

Value := 19538; 
Client.IOHandler.Write(Value); 

Pull code of server: AContext.Connection.IOHandler.ReadInt64; //receives 5930114809340100608

19538 in hex is 0x4C52.

5930114809340100608 in hex is 0x524C000000000000.

Notice a similarity?

19538 in network byte order is 4C 52 as a 16bit integer, and as 00 00 4C 52 as a 32bit integer. That is only 2-4 bytes, but an Int64 is 8 bytes, so there has to be another 4-6 bytes present otherwise ReadInt64 would not return. But lets assume there were extra 00 bytes present (in which case you are not handling your protocol data correctly). In order for ReadInt64 to return 5930114809340100608 from 8 bytes in network byte order, it would had to have received 52 4C 00 00 00 00 00 00, which does not come close to matching 19538 as a 16bit or 32bit integer in network byte order.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
-1

I've fixed it with code from http://codeverge.com/embarcadero.delphi.basm/fastest-best-way-to-reverse-byte-orde/1096017

It's a swap function that uses assembly, so now my code looks like: Swap8(AContext.Connection.IOHandler.ReadInt64);

The Swap8 function is:

function Swap8 (i: Int64): Int64;  register;
asm
  mov eax, dword [i]
  bswap eax
  mov dword [Result+4], eax
  mov eax, dword [i+4]
  bswap eax
  mov dword [Result], eax
end;
Friso
  • 2,328
  • 9
  • 36
  • 72
  • 5
    You don't need a separate swap function. The numeric `TIdIOHandler.Write()` and `TIdIOHandler.Read...()` methods have optional `Convert` parameters for dealing with byte swapping. – Remy Lebeau Apr 20 '15 at 17:24
  • 1
    This is absolutely the wrong solution. Use the concept of host to network and network to host. Don't ever explicitly swap bytes in your high level code. – David Heffernan Apr 21 '15 at 07:14