indy - 使用 BytesToInt64() 将 TIdBytes 转换为 Integer 的意外结果
问题描述
我正在使用该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;
推荐阅读
- javascript - 我可以使用 .trigger("change") 在事件处理程序完成之前更新复选框吗?
- reactjs - 类型错误:GoogleMap 未定义
- javascript - 在不使用 react-bootstrap 库的情况下将常规引导程序集成到反应中
- json - 如何从 nosql 中的忠诚度积分列中删除 % 符号,其中每个值都像 2%,3%
- r - 在 Plotly for R 中自定义文本(文本大小、文本颜色、文本角度)
- web-scraping - 如何将退避脚本插入我的网络抓取
- unity3d - AnalyticsSettings.initializeOnStartup = false; 仍然发送 appStart 事件
- azure - 每个工作日 18:30 和 23:00 运行的 cronjob 的命令是什么?
- powershell - CBH 的语法部分
- python - 在使用熊猫限制原始结构后,数据框缺少标题