【问题标题】:Using Crystal/Kemal to listen for UDP packets使用 Crystal/Kemal 监听 UDP 数据包
【发布时间】:2017-10-18 08:18:26
【问题描述】:

我一直在尝试使用 Crystal 和 Kemal 创建一个非阻塞服务器,它将 (a) 侦听发送给它的 UDP 消息流,然后 (b) 将该消息转发到 WebSocket 到任何浏览器已启动 ws 连接。

到目前为止,我能做到的最好的是:

require "kemal"
require "socket"

server = UDPSocket.new
server.bind "localhost", 1234
puts "Started..."

ws "/" do |socket|

    udp_working = true

    while udp_working
        message, client_addr = server.receive
        socket.send message
    end

    socket.on_close do
        puts "Goodbye..."
        udp_working = false
    end
end

这一切似乎有点不雅,而且确实没有按预期工作,因为:

  • 在正在启动的 Crystal 服务器和连接到 Crystal 服务器的第一个 Web 浏览器之间发送的所有 UDP 数据包都被缓存并在一个巨大的积压中发送
  • 浏览器从 WebSockets 断开连接没有得到正确处理,即 socket.on_close 没有被触发,并且循环继续直到我终止 Crystal 服务器

我希望有一个 server.on_message 类型的处理,它使我能够仅在收到 UDP 数据包时运行代码,而不是阻止服务器的持续轮询。有没有其他方法可以使用 Crystal/Kemal 实现这一目标?

谢谢!

【问题讨论】:

    标签: udp crystal-lang kemal


    【解决方案1】:

    您的方法存在几个问题:

    首先,socket.on_close 无法工作,因为这条线永远不会到达。 while 循环将一直运行到 udp_working == true,并且只会在 on_close 挂钩中设置为 false

    如果您不希望 UDP 数据报堆积,您需要从一开始就接收它们,并在没有连接 websocket 的情况下做任何您想做的事情(也许处置?)。 UDPServer 没有 on_message 挂钩,但 receive 已经是非阻塞的。所以你可以在一个循环中运行它(在它自己的光纤中)并在方法返回时采取行动。详情见Crystal Concurrency;也有使用 TCPSocket 的例子,不过 UDP 在这方面应该是类似的。

    【讨论】:

      【解决方案2】:

      Crystal 为您处理非阻塞,您需要在单独的光纤中编写阻塞代码并使用通道进行通信。 Crystal 将在幕后使用非阻塞代码和 select() 调用。

      此外,您需要一个框架或一些您自己的代码来将收到的消息复制到每个侦听的 websocket。这通常称为发布/订阅或发布/订阅。


      ws "/" do |socket|
      
         udp_working = true
      
         while udp_working
             message, client_addr = server.receive
             socket.send message
         end
      
         socket.on_close do
             puts "Goodbye..."
             udp_working = false
         end
      end
      

      即socket.on_close 没有被触发,

      你想先运行socket.on_close,否则事件处理程序不会被添加,因此直到循环之后才会运行,但循环实际上是无限的。此外,如果在检查udp_working var 和调用#send 之间关闭了套接字,socket.send message 将由于套接字关闭而出错的可能性很小

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-25
        • 1970-01-01
        • 1970-01-01
        • 2013-09-02
        • 1970-01-01
        相关资源
        最近更新 更多