为什么我收到了使用indy发送的不同的int?

时间:2015-04-20 10:54:22

标签: delphi indy delphi-2007 delphi-xe7

我已经检查过,当我将整数转换为十六进制时,它们分别变为4C52和524C000000000000,因此看起来字节是相反的。

客户端在Delphi XE7 for android上运行,服务器在Delphi 2007上运行。

我该如何解决这个问题?

推送客户代码:Client.IOHandler.Write(19538);

拉取服务器代码:AContext.Connection.IOHandler.ReadInt64; //receives 5930114809340100608

2 个答案:

答案 0 :(得分:8)

您没有考虑字节序或字节大小。

TIdIOHandler.Write()的整数重载接受主机字节顺序中的数值,根据平台可能是小端或大端,并将它们转换为传输默认为网络字节顺序,这是大端。整数TIdIOHandler.Read...()方法默认情况下期望数值以网络字节顺序到达,默认情况下会按顺序将其转换为主机。所以,如果你在双方都使用Indy,你不必担心这个细节,因为无论两端是哪个平台,读/写的结尾都是一致的。

TIdIOHandler.Write()数字重载和TIdIOHandler.Read...()数值方法都有一个可选的Convert参数,默认情况下为True。如果您将其设置为False,则会以主机字节顺序而非网络字节顺序发送/读取值。

更重要的是,您正在阅读Int64,但您没有发送Int64。对于各种整数类型,TIdIOHandler.Write()存在多个重载,并且无类型19538常量永远不会解析为Int64,并且存在此类重载。因此,您需要使用类型转换来告诉编译器使用Int64重载:

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

或使用变量:

var
  Value: Int64;

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

拉取服务器代码:AContext.Connection.IOHandler.ReadInt64; //收到5930114809340100608

19538 in hex 0x4C52

5930114809340100608(十六进制)为0x524C000000000000

注意相似性?

19538网络字节顺序为4C 52为16位整数,00 00 4C 52为32位整数。这只有2-4个字节,但Int64是8个字节,因此必须有另外4-6个字节,否则ReadInt64将不会返回。但我们假设存在额外的00个字节(在这种情况下,您没有正确处理协议数据)。为了使ReadInt64以8字节的网络字节顺序返回5930114809340100608,它必须接收52 4C 00 00 00 00 00 00,它不接近匹配19538作为网络字节顺序的16位或32位整数。

答案 1 :(得分:-1)

我已使用http://codeverge.com/embarcadero.delphi.basm/fastest-best-way-to-reverse-byte-orde/1096017

中的代码修复了它

它是一个使用汇编的交换函数,所以现在我的代码如下:Swap8(AContext.Connection.IOHandler.ReadInt64);

Swap8功能是:

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;