Using Crystal / Kemal to listen for UDP packets

I am trying to create a non-blocking server using Crystal and Kemal, which will (a) listen to the stream of UDP messages sent to it, and (b) then forward this message to WebSocket to any browsers that started the ws connection.

So far, the best I can do is:

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

All this seems a little inelegant, and really does not work as expected, because:

  • All UDP packets sent between the running Crystal server and the first web browser connecting to the Crystal server are cached and sent in one huge lag.
  • Browsers disconnected from WebSockets are not processed correctly, i.e. socket.on_close does not start and the loop continues until I finish the Crystal server

server.on_message, , UDP, , . Crystal/Kemal?

!

+4
2

:

-, socket.on_close , . while , udp_working == true, false on_close.

, UDP , , (, ?), -. on_message UDPServer, receive . , ( ) , . . Crystal Concurrency; TCPSocket, UDP .

+3

Crystal , . select() .

, , -, , - . / pub/sub.


...

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, , , , - . , , socket.send message - , udp_working var #send

+3

Source: https://habr.com/ru/post/1687705/


All Articles