【问题标题】:Lua - Socket receive with timer for other eventLua - 套接字接收其他事件的计时器
【发布时间】:2017-05-29 15:09:08
【问题描述】:

我正在尝试使用服务器套接字实现一个脚本,该脚本还将定期轮询来自多个传感器的数据(即每分钟的第 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 秒。

这是实现此功能的好方法,还是有(更简单)更好的方法(例如使用协程)?如果协程会更好,我该如何在我的场景中实现它们?

【问题讨论】:

  • 与您的问题无关,但不推荐使用table.getn
  • @hjpotter92 - 感谢您的评论,尽管我在这里使用它只是为了说明,并不打算在我的生产代码中使用它。不过,很高兴知道。

标签: timer lua luasocket


【解决方案1】:

要实现这一点,您需要某种多任务处理。 我会使用网络感知调度程序。

例如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())

【讨论】:

  • 感谢您的回复。我还没有尝试过代码,但是哇!看起来很完美!
【解决方案2】:

我认为使用不同语言的“cron”库可以很好地实现定期启动一些应用程序/代码。 比如lua中的cron lib你可以下载here

【讨论】:

  • 我正在尝试在嵌入式系统上实现这一点,并希望尽可能减少其内存占用,因为它在存储数据方面会占用很多空间。如果我不必添加另一个库就可以逃脱,我相信这将是一个点头。
  • 所以,尝试阅读cron.lua文件的源代码。它可能会有所帮助:github.com/kikito/cron.lua/blob/master/cron.lua
  • 我甚至在发布问题之前阅读了该代码,但不相信它提供了任何额外的东西。如果我确实遗漏了某些东西(请记住我的骨架代码示例),请您指出来吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-05
  • 1970-01-01
  • 2012-03-08
  • 2014-06-04
相关资源
最近更新 更多