使用 LUA 解码 UDP 消息

我相对于 LUA 和编程(自学)是比较新的,所以请温柔一点!

无论如何,我写了一个 LUA 脚本来读取一个游戏中的 UDP 消息。该消息的结构为:

DATAxXXXXaaaaBBBBccccDDDDeeeeFFFFggggHHHH
DATAx = 4 个字母的 ID,x = 控制字符
XXXX = 整数显示数据组(已知组)
aaaa...HHHHH = 8 个单精度浮点数

最后这一部分是我需要解码的数字。

如果我将接收到的消息打印出来,就像这样:

DATA*{V???A?A?...等。

使用_string.byte()_,我得到了像这样的一串字节(我已经“格式化”了这些字节以反映上面的结构)。

68 65 84 65/42/20 0 0 0/237 222 28 66/189 59 182 65/107 42 41 65/33 173 79 63/0 0 128 63/146 41 41 65/0 0 30 66/0 0 184 65

前 5 个字节当然是 DATA *。接下来 4 个字节是第 20 组数据。下一个字节序列是我需要解码的, 并且等于这些值:

237 222 28 66 = 39.218
189 59 182 65 = 22.779
107 42 41 65 = 10.573
33 173 79 63 = 0.8114
0 0 128 63 = 1.0000
146 41 41 65 = 10.573
0 0 30 66 = 39.500
0 0 184 65 = 23.000

我找到了使用 BitConverter.ToSingle() 进行解码的 C# 代码,但我还没有找到这样的 Lua 代码。有什么想法吗?

点赞
用户4403144
用户4403144

这是 IEEE-754 单精度二进制的小端字节序:

例如,0 0 128 63 可以表示为:

00111111 10000000 00000000 00000000 (63) (128) (0) (0)

为什么这等于 1 需要了解 IEEE-754 表示的最基本原理,即其指数和尾数的使用。请参见 这里

请参见 @Egor 的上面的答案,以了解如何在 Lua 5.3 中使用 string.unpack() 和一个你可以在早期版本中使用的可能实现。

2018-09-08 20:51:56
用户1847592
用户1847592

你用的是什么版本的 Lua?

这段代码可以在 Lua 5.3 上运行:

local str = "DATA*\20\0\0\0\237\222\28\66\189\59\182\65..."
-- 从字符串的第 10 位开始读取两个浮点值
print(string.unpack("<ff", str, 10))  -->  39.217700958252  22.779169082642 18
-- 18(返回的第三个值)是字符串中的下一个位置

Lua 5.1 上,你需要编写一个特殊函数(或从 François Perrad 的 git 仓库中偷取 ):

local function binary_to_float(str, pos)
   local b1, b2, b3, b4 = str:byte(pos, pos+3)
   local sign = b4 > 0x7F and -1 or 1
   local expo = (b4 % 0x80) * 2 + math.floor(b3 / 0x80)
   local mant = ((b3 % 0x80) * 0x100 + b2) * 0x100 + b1
   local n
   if mant + expo == 0 then
      n = sign * 0.0
   elseif expo == 0xFF then
      n = (mant == 0 and sign or 0) / 0
   else
      n = sign * (1 + mant / 0x800000) * 2.0^(expo - 0x7F)
   end
   return n
end

local str = "DATA*\20\0\0\0\237\222\28\66\189\59\182\65..."
print(binary_to_float(str, 10))  --> 39.217700958252
print(binary_to_float(str, 14))  --> 22.779169082642
2018-09-09 05:49:54