Lua的HTTP解析器

时间:2017-09-11 09:18:40

标签: http lua

我试图在Lua中解析http POST请求。我的实现工作,但吃掉了很多CPU负载。这很关键,因此它位于嵌入式平台上。

我已经查看了其他实现,但它们不合适,因为我的图像几乎不适合内存,因此我不会使用其他库。我推出了自己的解析器,但它使用了太多的系统资源。问题是如何优化它以降低CPU负载。

这是一个基于OpenWRT的系统,所以我只有Lua 5.1。这是寻找边界的核心函数(在str变量中)。它逐块读取输入,并寻找它。

另一种解决方案是使用LUCI库来完成繁重工作,但我不希望我的代码集成到LUCI中。

--look for a pattern (str) and copy input until it is found to the output.
local function writeuntil(in_fp, str, out_fp)

    local buff = ""
    local ret = false
    local bs = 4096 --Block size. The amount of data to read at once

    local c = in_fp:read(bs)
    local strStartPos = 1

    while c do
        local blockLen = string.len(c) --Not sure that a whole block is read, so get the size of the actual block.
        local found = string.find(c, str, 1, true) --Try to locate str, so we don't have much work.
        if (found ~= nil) then
            if found > 2 then
                out_fp:write(string.sub(c, 1, found - 1))
            end
            ret = true
            break --we are done
        else --Try to mach str till the end of the block
            local strPos = string.find(c, string.sub(str, strStartPos, strStartPos), 1, true) --try to locate the first character
            if strPos then --There is a starting character in the block
                if (strPos > 1) then
                        out_fp:write(string.sub(c, 1, strPos - 1))
                end
                for i = strPos, blockLen do --iterate through the block
                    local ch = string.sub(c, i, i)
                    if ch == string.sub(str, strStartPos, strStartPos) then
                        buff = buff .. ch
                        if string.len(buff) == string.len(str) then
                            ret = true
                            break --We're done
                        end
                        strStartPos = strStartPos + 1
                    else --Lost track. Output.
                        if string.len(buff) > 0 then
                            out_fp:write(buff)
                            buff = ""
                        end
                        out_fp:write(ch)
                        strStartPos = 1
                    end
                end
            else
                out_fp:write(c)
            end
        end
        if ret then
            break
        end
        c = in_fp:read(bs) --read next block
    end
    return ret
end

1 个答案:

答案 0 :(得分:0)

叶戈尔,你是对的,但我最终解决了这个问题。它现在使用的CPU少得多。这不完美,因此scp更快(虽然这是用C实现的)。

--look for a pattern (str) and copy input until it is found to the output.
local function writeuntil(in_fp, str, out_fp)

    local buff = ""
    local ret = false
    local bs = 4096 --Block size. The amount of data to read at once

    local c = in_fp:read(bs)
    local strStartPos = 1
    local lastStrPos = 1
    local needData = true

    while c do
        local blockLen = string.len(c) --Not sure that a whole block is read, so get the size of the actual block.
        local found = string.find(c, str, 1, true) --Try to locate str, so we don't have much work.
        if (found ~= nil) then
            if found > 1 then
                if #buff > 0 then
                    out_fp:write(buff)
                end
                out_fp:write(string.sub(c, 1, found - 1))
            end
            ret = true
            break --we are done
        else --Try to mach str till the end of the block
            local strPos = string.find(c, string.sub(str, strStartPos, strStartPos), lastStrPos, true) --try to locate the first character
            if strPos then --There is a starting character in the block
                out_fp:write(string.sub(c, lastStrPos, strPos - 1))
                for i = strPos, blockLen do --iterate through the block
                    local ch = string.sub(c, i, i)
                    if ch == string.sub(str, strStartPos, strStartPos) then
                        buff = buff .. ch
                        if string.len(buff) == string.len(str) then
                            ret = true
                            break --We're done
                        end
                        strStartPos = strStartPos + 1
                        lastStrPos = i + 1
                    else --Lost track. Output.
                        if string.len(buff) > 0 then
                            out_fp:write(buff)
                            buff = ""
                        end
                        out_fp:write(ch)
                        strStartPos = 1
                        if i == blockLen then
                            needData = true
                        else
                            lastStrPos = i + 1
                            needData = false
                        end
                        break
                    end
                end
            else
                if ret == false then
                    if string.len(buff) > 0 then
                        out_fp:write(buff)
                        buff = ""
                    end
                    out_fp:write(string.sub(c, lastStrPos))
                    lastStrPos = 1
                    needData = true
                else
                    break
                end
            end
        end
        if ret then
            break
        end
        if needData then
            c = in_fp:read(bs) --read next block
            lastStrPos = 1
        end
    end
    return ret
end