Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Crystal/Kemal侦听UDP数据包_Udp_Crystal Lang_Kemal - Fatal编程技术网

使用Crystal/Kemal侦听UDP数据包

使用Crystal/Kemal侦听UDP数据包,udp,crystal-lang,kemal,Udp,Crystal Lang,Kemal,我一直在尝试使用Crystal和Kemal创建一个非阻塞服务器,该服务器将(a)侦听发送给它的UDP消息流,然后(b)将该消息转发到WebSocket,发送到任何启动ws连接的浏览器 到目前为止,我能做的最好的事情是: require "kemal" require "socket" server = UDPSocket.new server.bind "localhost", 1234 puts "Started..." ws "/" do |socket| udp_workin

我一直在尝试使用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数据包都被缓存,并在一个巨大的积压中发送
  • 未正确处理从WebSocket断开的浏览器,即未触发socket.on_close,循环将继续,直到我终止Crystal服务器
我希望有一个server.on_消息类型处理,这将使我能够仅在收到UDP数据包时运行代码,而不是阻止服务器的连续轮询。使用Crystal/Kemal是否有其他方法实现这一点


谢谢

您的方法有几个问题:

首先,
socket.on\u close
无法工作,因为从未到达此行。只要
udp\u working==true,while循环就会运行,并且它只会在
on\u close
钩子中设置为
false


如果您不想让UDP数据报堆积起来,您需要从一开始就接收它们,如果没有连接websocket,则需要执行任何您想要的操作(可能是处置?)。
UDPServer
的消息上没有
,但是
receive
已经是非阻塞的。因此,您可以在循环中运行它(在它自己的光纤中),并在该方法返回时执行操作。详情见:;还有一个使用TCPSocket的示例,但UDP在这方面应该类似。

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

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


i、 e.未触发插座on_关闭

您需要先运行
socket.on\u close
,否则事件处理程序将不会被添加,因此直到循环结束后才会运行,但是循环实际上是无限的。此外,如果在检查
udp\u工作
var和调用
\send
var之间关闭套接字,则
socket.send message
很可能由于套接字关闭而出错

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