我已经检查过,当我将整数转换为十六进制时,它们分别变为4C52和524C000000000000,因此看起来字节是相反的。
客户端在Delphi XE7 for android上运行,服务器在Delphi 2007上运行。
我该如何解决这个问题?
推送客户代码:Client.IOHandler.Write(19538);
拉取服务器代码:AContext.Connection.IOHandler.ReadInt64; //receives 5930114809340100608
答案 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;