首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >解析LIFX报头

解析LIFX报头
EN

Stack Overflow用户
提问于 2016-01-04 06:57:28
回答 1查看 139关注 0票数 3

我用这段代码从我的LIFX灯泡中获得了一个数据包:

代码语言:javascript
复制
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)

通过这样做,我收到的一包数据是:

代码语言:javascript
复制
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标头描述文档来解析这一点,使用以下代码:

代码语言:javascript
复制
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。

我在这里做错了什么来得到这个错误的价值?

另外:当我将代码更改为:

代码语言:javascript
复制
<< 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

这告诉我:

代码语言:javascript
复制
** (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>>

这导致我认为我在分析代码时做错了什么。我认为第二个代码块更接近于一个答案,但它显然不起作用。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-01-04 09:34:16

您的问题在于二进制模式匹配。

代码语言:javascript
复制
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(一个字节)。

代码语言:javascript
复制
iex(1)> <<< a, b :: bytes>> = <<1,2,3>>
<<1, 2, 3>>
iex(1)> a
1
iex(1)> b
<<2, 3>>

所以在你的例子中,你应该使用:

代码语言:javascript
复制
<< 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位大小的模式匹配。

代码语言:javascript
复制
<<a :: size(1), b :: size(2)>> =  <<2 :: size(3)>>

payload :: bytes的意思是,它将匹配任何可以被8整除的大小。在我的回答中,16和32显然可以被8整除,其余的是2+1+1+ 12 = 16位。

在您的编辑中,您有16位和32位,但是有2位“挂起”,这使得模式匹配失败。

接收代码是正确的。你可以用手检查。第一个字节41实际上匹配二进制文件的大小,以此类推。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34586110

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档