2015-09-12 6 views
2

Я пытаюсь реализовать скрипт с серверным сокетом, который также будет периодически опросить данные с нескольких датчиков (т. Е. На 59-й секунде каждую минуту). Я не хочу сериализовать данные на диск, а хранить его в таблице, которую сокет будет отвечать при опросе. Вот некоторый эскиз код, чтобы показать, что я пытаюсь сделать (я не вхожу в клиентском код, который получает доступ к этому серверу, но эта часть OK)Lua - Socket receive с таймером для другого события

#!/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-ю секунду.

Это хороший способ реализовать это или есть (более простой) способ сделать это (скажем, используя сопрограммы)? Если сопрограммы будут лучше, как мне реализовать их для моего сценария?

+1

Не относится к вашему вопросу, но 'table.getn' устарело. – hjpotter92

+0

@ hjpotter92 - спасибо за комментарий, хотя я использовал его здесь только для иллюстрации и не собирался использовать его в своем производственном коде. Тем не менее, приятно знать. – Nepaluz

ответ

4

Для этого вам потребуется какая-то многозадачность. Я бы использовал планировщик, ориентированный на сеть.

например. 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()) 
+0

Спасибо за ответ. Я еще не пробовал код, но WOW! отлично! – Nepaluz

0

Я думаю, что периодически запуск некоторых приложений/кодов хорошо реализуется с помощью библиотек cron на разных языках. Например, cron lib in lua вы можете скачать here.

+0

Я пытаюсь реализовать это на встроенной системе и хотел бы как можно меньше сохранить свой объем памяти, учитывая, что это займет много времени с точки зрения хранения данных. Если мне удастся уйти, не добавив еще одну библиотеку, я уверен, что это будет к ней. – Nepaluz

+0

Итак, попробуйте прочитать исходный код файла cron.lua. Это может помочь: https://github.com/kikito/cron.lua/blob/master/cron.lua – Vyacheslav

+0

Я прочитал этот код, даже до публикации вопроса, но не поверил, что он предложил что-то дополнительное. Если бы я что-то пропустил (имея в виду образец кода скелета), не могли бы вы указать на это? – Nepaluz

 Смежные вопросы

  • Нет связанных вопросов^_^