Lua - 使用定时器接收Socket并处理其他事件

我正在尝试使用服务器套接字实现一个脚本,它也会定期轮询多个传感器的数据(例如每分钟的第59秒)。我不想将数据序列化到磁盘中,而是将其保存在一个表中,这个套接字将在轮询时回复这个表。

这是一个简要的代码示例,以说明我正在做什么(我没有包括访问此服务器的客户端代码,但该部分是正常的)

我担心服务器可能会偶尔阻塞,因此我会错过第59秒。

这是实现这个过程的好方法,还是有(更简单)更好的方法来实现这个过程(例如使用协程)?如果协程更好,那么如何为我的情况实现它们?

点赞
用户1979882
用户1979882

我认为周期性地启动一些应用程序/代码很好地实现了各种语言中的“cron”库。

例如,在 Lua 中,您可以在此处下载 cron 库。

2015-09-13 11:50:29
用户282536
用户282536

为了实现这个,你需要一些形式的多任务处理。我会使用网络感知调度程序,例如 cqueues

代码如下:

local cqueues = require "cqueues"
local cs = require "cqueues.socket"

local data = {}
local count = 1
local function pollSensors()
    -- 在这里进行传感器轮询并添加到表中,例如 os.time()
    table.insert(data, os.time() .."\t" .. tostring(count))
    count = count + 1
end

local function handle_client(client)
    client:setmode("b", "bn") -- 打开 socket 的二进制模式,关闭缓冲
    -- 从问题中移植的代码:
    client:settimeout(2) -- 我不确定为什么你选择了 2 秒的超时时间
    local line, err = client:read("*l") -- 使用 cqueues,此读取将不会阻塞整个程序,而只是在数据到达时产生当前协程的切换。
    -- 处理接收到的行以确定响应
    -- 为举例说明,我将发送表中的项目数量
    if not err then
        assert(client:write(string.format("Records: %d\n", #data)))
    end
    client:close()
end

local cq = cqueues.new() -- 创建一个新的调度程序
-- 创建第一个协程,等待传入的客户机
cq:wrap(function()
    local server = cs.listen{host = "0.0.0.0"; port = "0"}
    local fam, ip, port = server:localname()
    print(string.format("Now listening on ip=%s port=%d", ip, port))
    for client in server:clients() do -- 遍历接受的客户机
        -- 为每个客户机创建一个新的协程,将客户机传递进去
        cqueues.running():wrap(handle_client, client)
    end
end)
-- 创建第二个协程,读取传感器
cq:wrap(function()
    while true do
        -- 我假设你只想每 60 秒读取一次,而不是实际上在每一分钟的第 59 秒进行读取。
        pollSensors()
        cqueues.sleep(60)
    end
end)
-- 运行调度程序,直到所有线程退出
assert(cq:loop())
2015-09-14 01:23:22