我用这段代码从我的LIFX灯泡中获得了一个数据包:
defmodule LIFX do
def listen(port) do
udp_options = [:binary, {:reuseaddr, true}, { :active, false }]
{ :ok, socket } = :gen_udp.open(port, udp_options)
do_listen(socket)
end
def do_listen(socket) do
case :gen_udp.recv(socket, 0) do
{ :ok, { _ip, _port, data } } ->
IO.inspect(data)
end
end
end
LIFX.listen(56700)通过这样做,我收到的一包数据是:
data = <<41, 0, 0, 84, 0, 0, 0, 0, 208, 115, 213, 0, 249, 20, 0, 0, 76, 73, 70, 88, 86, 50, 0, 0, 196, 240, 247, 239, 158, 36, 38, 20, 3, 0, 0, 0, 1, 124, 221, 0, 0>>我试图通过以下LIFX标头描述文档来解析这一点,使用以下代码:
data = <<41, 0, 0, 84, 0, 0, 0, 0, 208, 115, 213, 0, 249, 20, 0, 0, 76, 73, 70, 88, 86, 50, 0, 0, 196, 240, 247, 239, 158, 36, 38, 20, 3, 0, 0, 0, 1, 124, 221, 0, 0>>
<< s :: unsigned-little-integer-size(16),
origin :: unsigned-little-integer-size(8),
tagged,
addressable,
protocol :: unsigned-little-integer-size(16),
payload :: bytes >> = data然而,对于tagged of 84,这给了我一个看似不正确的值。LIFX文档说这应该是布尔型的,所以我期望的是1或0,而不是84。
我在这里做错了什么来得到这个错误的价值?
另外:当我将代码更改为:
<< s :: unsigned-little-integer-size(16),
origin :: unsigned-little-integer-size(8),
tagged :: unsigned-little-integer-size(1),
addressable :: unsigned-little-integer-size(1),
protocol :: unsigned-little-integer-size(16),
payload :: bytes >> = data这告诉我:
** (MatchError) no match of right hand side value: <<41, 0, 0, 84, 0, 0, 0, 0, 208, 115, 213, 0, 249, 20, 0, 0, 76, 73, 70, 88, 86, 50, 0, 0, 196, 240, 247, 239, 158, 36, 38, 20, 3, 0, 0, 0, 1, 124, 221, 0, 0>>这导致我认为我在分析代码时做错了什么。我认为第二个代码块更接近于一个答案,但它显然不起作用。
发布于 2016-01-04 09:34:16
您的问题在于二进制模式匹配。
data = <<41, 0, 0, 84, 0, 0, 0, 0, 208, 115, 213, 0, 249, 20, 0, 0, 76, 73, 70, 88, 86, 50, 0, 0, 196, 240, 247, 239, 158, 36, 38, 20, 3, 0, 0, 0, 1, 124, 221, 0, 0>>
<< s :: unsigned-little-integer-size(16),
origin :: unsigned-little-integer-size(8),
tagged,
addressable,
protocol :: unsigned-little-integer-size(16),
payload :: bytes >> = data您指定的大小总是以位为单位,如果没有大小,则默认为8(一个字节)。
iex(1)> <<< a, b :: bytes>> = <<1,2,3>>
<<1, 2, 3>>
iex(1)> a
1
iex(1)> b
<<2, 3>>所以在你的例子中,你应该使用:
<< s :: unsigned-little-integer-size(16),
origin :: unsigned-little-integer-size(2),
tagged :: size(1),
addressable :: size(1),
protocol :: size(12),
source :: size(32),
payload :: bytes >> = data注意标记、可寻址和协议上的大小。您还可以指定endianness,就像对于原产地一样。
解析时,请确保二进制文件的大小与数据包报头中指定的大小相匹配。否则,您应该构建一种能够以块形式解析数据包的机制。
有关二进制模式匹配的更多信息。
编辑问题后续:
二进制大小需要匹配。例如,如果您只有3位,则必须有3位大小的模式匹配。
<<a :: size(1), b :: size(2)>> = <<2 :: size(3)>>payload :: bytes的意思是,它将匹配任何可以被8整除的大小。在我的回答中,16和32显然可以被8整除,其余的是2+1+1+ 12 = 16位。
在您的编辑中,您有16位和32位,但是有2位“挂起”,这使得模式匹配失败。
接收代码是正确的。你可以用手检查。第一个字节41实际上匹配二进制文件的大小,以此类推。
https://stackoverflow.com/questions/34586110
复制相似问题