【问题标题】:Using IO#pos and IO#seek with UDPSocket将 IO#pos 和 IO#seek 与 UDPSocket 一起使用
【发布时间】:2019-12-15 15:57:19
【问题描述】:

我有一个UDPSocket 实例:

io = UDPSocket.new
io.connect "8.8.4.4", 53

它通过端口 53 连接到 DNS 服务器,发送 DNS 查询并检索结果。 DNS 内置了指针形式的消息压缩,参见RFC 1035, 4.1.4。消息压缩。资源记录可以包含指向问题域的消息偏移量,而不是域名。这样就不必为每条记录重复域名。

我在我的资源记录类中实现了如下:

 def self.from_io(io : IO, format : IO::ByteFormat) : self
    domain = ""
    loop do
      codepoint = UInt8.from_io io, format
      break if codepoint == 0
      if codepoint >= 192 # if the octet starts with 11 as defined in the rfc
        current_pos = io.pos
        pointer = UInt8.from_io io, format
        io.seek(pointer)
        # read the string...
      end
      # ...
    end
end

这不起作用,因为UDPSocket 没有实现IO#posIO#seek

Unhandled exception: Unable to pos

为了解决这个问题,我创建了一个使用 IO::Memory 的子类:

class DNS::DNSSocket < UDPSocket
  def initialize(family : Socket::Family = Socket::Family::INET)
    super family
    @memory = IO::Memory.new
  end

  def read(slice : Bytes)
    if slice.size + pos > @memory.size
      super slice
      @memory.write slice
    else
      @memory.read slice
    end
    slice.size
  end

  def pos
    @memory.pos
  end

  def pos=(value)
    @memory.pos = value
  end

  def seek(offset, whence : Seek = IO::Seek::Set)
    @memory.seek offset, whence
  end

  def clear
    @memory.clear
  end
end

我的问题如下:

  1. 这是一个好的解决方案,还是您知道更优雅的方法?

  2. IO::Memory 实例需要在每条消息后重置。是否可以在我的 DNSSocket 实现中的数据报(数据包)的末尾或开头调用clear?我也可以在我的消息解析器中调用它,但我不想这样做。

【问题讨论】:

    标签: sockets dns crystal-lang


    【解决方案1】:

    UDP 是一种无连接通信模型,因此不支持流式传输。 UDPSocket 继承 IO,但它不应该,我认为这实际上是由 Socket 继承自 IO 引起的 API 缺陷。它仍然有效,因为 IO 实现使用的底层系统调用也适用于 UDP 套接字。但是使用UDPSocket 作为 IO 并不理想,应该避免。由于无论如何数据报通常都是短消息,因此将它们完全加载到内存中是完全可以的。

    所以,我建议改用UDPSocket#receive,这样您就可以轻松地将切片包装在IO::Memory 中。

    【讨论】:

      【解决方案2】:

      添加到其他回复中,解决方案比我想象的要简单得多。

      slice = Bytes.new(512)
      socket.read slice
      io = IO::Memory.new slice
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-10-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多