Lua-Socket receive с таймером для другого события
Я пытаюсь реализовать сценарий с сокетом сервера, который также будет периодически опрашивать данные с нескольких датчиков (т. е. на 59-й секунде каждой минуты). Я не хочу сериализовывать данные на диск, а скорее хранить их в таблице, на которую сокет будет отвечать при опросе.
Вот некоторые наброски кода, чтобы проиллюстрировать, что я пытаюсь сделать (я не включил клиентский код, который обращается к этому серверу, но эта часть в порядке)
#!/usr/bin/env lua
local socket = require("socket")
local server = assert(socket.bind("*", 0))
local ip, port = server:getsockname()
local data = {}
local count = 1
local function pollSensors()
-- I do the sensor polling here and add to table e.g os.time()
table.insert(data, os.time() .."t" .. tostring(count))
count = count + 1
end
while true do
local client = server:accept()
client:settimeout(2)
local line, err = client:receive()
-- I do process the received line to determine the response
-- for illustration I'll just send the number of items in the table
if not err then client:send("Records: " ..table.getn(data) .. "n") end
client:close()
if os.time().sec == 59 then
pollSensors()
end
end
Я обеспокоен тем, что сервер может случай(ы) блок, и поэтому я пропущу 59-ю секунду.
Это хороший способ реализовать это или есть (более простой) лучший способ сделать это (скажем, используя сопрограммы)? Если сорутинги были бы лучше, как я могу реализовать их для своего сценария?
2 ответов:
Для этого вам понадобится своего рода многозадачность. Я бы использовал сетевой планировщик.
Например, cqueues будет выглядеть так:
local cqueues = require "cqueues" local cs = require "cqueues.socket" local data = {} local count = 1 local function pollSensors() -- I do the sensor polling here and add to table e.g os.time() table.insert(data, os.time() .."\t" .. tostring(count)) count = count + 1 end local function handle_client(client) client:setmode("b", "bn") -- turn on binary mode for socket and turn off buffering -- ported code from question: client:settimeout(2) -- I'm not sure why you chose a 2 second timeout local line, err = client:read("*l") -- with cqueues, this read will not block the whole program, but just yield the current coroutine until data arrives. -- I do process the received line to determine the response -- for illustration I'll just send the number of items in the table if not err then assert(client:write(string.format("Records: %d\n", #data))) end client:close() end local cq = cqueues.new() -- create a new scheduler -- create first coroutine that waits for incoming clients 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 -- iterates over `accept`ed clients -- create a new coroutine for each client, passing the client in cqueues.running():wrap(handle_client, client) end end) -- create second coroutine that reads sensors cq:wrap(function() while true do -- I assume you just wanted to read every 60 seconds; rather than actually *on* the 59th second of each minute. pollSensors() cqueues.sleep(60) end end) -- Run scheduler until all threads exit assert(cq:loop())
Я думаю, что периодически запускаемые некоторые приложения / коды хорошо реализуются с библиотеками "cron" на разных языках. Например, cron lib в lua вы можете скачать здесь.
Comments