使用 BytesToInt64() 将 TIdBytes 转换为 Integer 的意外结果
Unexpected results converting TIdBytes to Integer using BytesToInt64()
我正在使用 TIdUDPServer.OnUDPRead
事件读取 UDP 数据包。每个数据包中嵌入了一个 8 字节 QUint64
,代表一个无线电频率。我正在尝试读取该频率。
所有使用 BytesToInt64()
的尝试都会导致错误的结果。我已通过使用 Wireshark 读取十六进制值并使用基于 Web 的十六进制到十进制转换器来验证数据是否正确。
我知道数据包中的频率从位置 23 开始,长度为 8 个字节。
procedure TWSJTxUDPClient.IdUDPServer1UDPRead(AThread: TIdUDPListenerThread;
const AData: TIdBytes; ABinding: TIdSocketHandle);
var
FreqInt: Int64;
begin
FreqInt := BytesToInt64(AData,23);
LabelFreq.Caption := IntToStr(FreqInt);
end;
这是电线上的十六进制数据,从位置 23 开始:
00 00 00 00 00 6b f0 d0
表示频率为 7074000 赫兹。
我上面的代码生成的频率值为 58811137507983360。
我还通过在表示频率的字符串上使用 Ord()
函数读取每个字节来确认十六进制数据。
FreqStr := BytesToString(Adata,23,8);
Int8 := Ord(FreqStr[8]);
Int8 现在 = 208 - 0xd0 的正确值。对字节 5、6 和 7 执行相同操作。已确认。
所以我知道我缺少一些基本的东西。
您没有考虑字节序。
十进制 7074000
是十六进制 0x6BF0D0
。十进制 58811137507983360
是十六进制 0xD0F06B00000000
。看到相似之处了吗?它们的字节顺序相反。
您的数据包中的字节采用网络字节顺序(大端),但您的机器使用的是小端。您需要交换 Int64
的字节。您可以为此使用 Indy 的 GStack.NetworkToHost()
方法:
procedure TWSJTxUDPClient.IdUDPServer1UDPRead(AThread: TIdUDPListenerThread; const AData: TIdBytes; ABinding: TIdSocketHandle);
var
FreqInt: Int64;
begin
FreqInt := BytesToInt64(AData, 23);
FreqInt := Int64(GStack.NetworkToHost(UInt64(FreqInt)));
LabelFreq.Caption := IntToStr(FreqInt);
end;
我正在使用 TIdUDPServer.OnUDPRead
事件读取 UDP 数据包。每个数据包中嵌入了一个 8 字节 QUint64
,代表一个无线电频率。我正在尝试读取该频率。
所有使用 BytesToInt64()
的尝试都会导致错误的结果。我已通过使用 Wireshark 读取十六进制值并使用基于 Web 的十六进制到十进制转换器来验证数据是否正确。
我知道数据包中的频率从位置 23 开始,长度为 8 个字节。
procedure TWSJTxUDPClient.IdUDPServer1UDPRead(AThread: TIdUDPListenerThread;
const AData: TIdBytes; ABinding: TIdSocketHandle);
var
FreqInt: Int64;
begin
FreqInt := BytesToInt64(AData,23);
LabelFreq.Caption := IntToStr(FreqInt);
end;
这是电线上的十六进制数据,从位置 23 开始:
00 00 00 00 00 6b f0 d0
表示频率为 7074000 赫兹。
我上面的代码生成的频率值为 58811137507983360。
我还通过在表示频率的字符串上使用 Ord()
函数读取每个字节来确认十六进制数据。
FreqStr := BytesToString(Adata,23,8);
Int8 := Ord(FreqStr[8]);
Int8 现在 = 208 - 0xd0 的正确值。对字节 5、6 和 7 执行相同操作。已确认。
所以我知道我缺少一些基本的东西。
您没有考虑字节序。
十进制 7074000
是十六进制 0x6BF0D0
。十进制 58811137507983360
是十六进制 0xD0F06B00000000
。看到相似之处了吗?它们的字节顺序相反。
您的数据包中的字节采用网络字节顺序(大端),但您的机器使用的是小端。您需要交换 Int64
的字节。您可以为此使用 Indy 的 GStack.NetworkToHost()
方法:
procedure TWSJTxUDPClient.IdUDPServer1UDPRead(AThread: TIdUDPListenerThread; const AData: TIdBytes; ABinding: TIdSocketHandle);
var
FreqInt: Int64;
begin
FreqInt := BytesToInt64(AData, 23);
FreqInt := Int64(GStack.NetworkToHost(UInt64(FreqInt)));
LabelFreq.Caption := IntToStr(FreqInt);
end;