gpt4 book ai didi

ruby - 如何从外部停止udp_server_loop

转载 作者:行者123 更新时间:2023-12-03 11:59:11 26 4
gpt4 key购买 nike

我用Ruby编写了小UDP服务器:

def listen
puts "Started UDP server on #{@port}..."

Socket.udp_server_loop(@port) do |message, message_source|
puts "Got \"#{message}\" from #{message_source}"

handle_incoming_message(message)
end
end

我在一个单独的线程中启动它:

thread = Thread.new { listen }

有没有一种方法可以从线程外部优雅地停止 udp_server_loop而不只是杀死它( thread.kill)?我也不想通过接收任何UDP消息从内部停止它。 udp_server_loop可能不是适合我的工具吗?

最佳答案

我认为您无法使用udp_server_loop做到这一点(尽管您也许可以使用它使用的某些方法)。您将不得不在自己的循环中调用 IO::select ,并用某种信号通知它退出,并通过某种方式唤醒线程,这样就不必发送数据包来停止它了。

一种简单的方法是使用select的timeout选项和一个变量来设置,以指示您希望线程结束,例如:

@halt_loop = false

def listen
puts "Started UDP server on #{@port}..."
sockets = Socket.udp_server_sockets(@port)

loop do
readable, _, _ = IO.select(sockets, nil, nil, 1) # timeout 1 sec
break if @halt_loop
next unless readable # select returns nil on timeout

Socket.udp_server_recv(readable) do |message, message_source|
puts "Got \"#{message}\" from #{message_source}"

handle_incoming_message(message)
end
end
end

然后,当您要停止线程时,可以将 @halt_loop设置为true。

不利的一面是它正在有效地轮询。如果减少超时,则可能在空循环上执行更多工作,而如果增加超时,则在停止线程时必须等待更长的时间。

另一个稍微复杂一点的解决方案是使用 pipe 并使select与套接字一起监听。然后,您可以直接发出信号以完成 select并退出线程。
@read, @write = IO.pipe
@halt_loop = false

def listen
puts "Started UDP server on #{@port}..."
sockets = Socket.udp_server_sockets(@port)
sockets << @read

loop do
readable, _, _ = IO.select(sockets)
break if @halt_loop

readable.delete @read

Socket.udp_server_recv(readable) do |message, message_source|
puts "Got \"#{message}\" from #{message_source}"

handle_incoming_message(message)
end
end
end

def end_loop
@halt_loop = true
@write.puts "STOP!"
end

要退出线程,您只需要调用 end_loop即可,该命令会设置 @halt_loop标志,然后将其写入管道,使另一端可读,并使另一个线程从 select返回。

您可以让此代码检查可读的 IO,如果其中之一是管道的读取端而不是使用变量,则退出,但至少在Linux上存在潜在的错误,其中select调用可能返回文件描述符为实际不可读时可读。我不知道Ruby是否可以解决这个问题,所以安全胜过遗憾。

另外,在将管道传递给 readable之前,请确保从 udp_server_recv数组中删除管道。它不是套接字,如果不这样做,将导致异常。

这种技术的缺点是管道“在所有平台上都不可用”。

关于ruby - 如何从外部停止udp_server_loop,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57575662/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com