NodeMCU 超小型自动更新 Web 服务器内存溢出问题

我正在测试一个具有自动更新功能的 Lua 网络服务器。HTML 代码每秒重定向到网络服务器本身。因此,客户端的 Web 浏览器总是从服务器获取新数据,而不是使用浏览器的缓存。

如果我连接任何一个客户端(我的 PC 或智能手机)一段时间后,NodeMCU 板会崩溃,并显示以下消息:

PANIC:在调用 Lua API 时发生未保护的错误(SO-WebSrv-Test.lua:27:内存溢出)

我使用 Marcel Stoer 的代码,他回答了类似“内存溢出”问题的[问题](https://stackoverflow.com/questions/37315548/esp8266-nodemcu-running-out-of-heap-memory)。

我修改了 Marcel 的 Lua 代码,但是该代码仍会随着时间的推移消耗所有堆内存。

我稍微缩小了问题的范围:如果 HTML 代码的刷新频率低于 30 秒,则该代码会占用堆内存。

那么我需要如何修改此代码才能实现常数堆内存使用率?

最好的问候。

Stefan

tmr.alarm(0, 1000, 1, function()
   if wifi.sta.getip() == nil then
      print("trying to connect to AccessPoint...")
   else
      own_ip, netmask, gateway=wifi.sta.getip()
      print("connected to AccessPoint:")
      print("IP Info: \nIP Address of this device: ",own_ip)
      print("Netmask: ",netmask)
      print("Gateway Addr: ",gateway,"\n")
      print("type IP-Address "..own_ip.." into your browser to display SHT-31-website")
      tmr.stop(0)
   end
end)

counter = 0
srv = net.createServer(net.TCP, 28800)
print("Server created... \n")

srv:listen(80, function(conn)
    conn:on("receive", function(sck, request)
        local message = {}
        counter = counter + 1
        message[#message + 1] = "<head> <meta http-equiv=refresh content=1; URL=http://"..own_ip.."> </head>"
        message[#message + 1] = "<h1> ESP8266 SHT-31 Web Server Ver 003</h1>"
        message[#message + 1] = "<h2>some more text blabla blub"..counter.."</h2>"
        local function send(sk)
            if #message > 0 then
                sk:send(table.remove(message, 1))
            else
                sk:close()
                message = nil
                print("Heap Available:" .. node.heap())
            end
        end
        sck:on("sent", send)
        send(sck)
    end)
end)
点赞
用户131929
用户131929

你没有告诉我们你使用的固件版本。我在 Chromium 浏览器中测试了一个最近的版本,并没有看到任何内存问题。在进行了 700 多次重新加载后,堆的使用非常稳定。

今年早些时候,我们不得不降低 TCP TIME_WAIT 参数值,因为太多保持在等待时间状态的已弃用套接字会占用内存。解释如下:

等待时间

(服务器或客户端) 代表等待足够的时间来确保远程 TCP 收到了其连接终止请求的确认。 [根据 RFC 793,连接可以在最长为四分钟的两个 MSL (最大分段生存期) 中保持等待状态]。

来源:https://en.wikipedia.org/wiki/Transmission_Control_Protocol#Protocol_operation

更多细节信息:https://www.rfc-editor.org/rfc/rfc7230#section-6.6

然而:

  • 你似乎打算将 HTML 通过 HTTP 发送回客户端,但没有告诉它,它可能不喜欢这样
  • 如果你的客户端(一个浏览器?)没有及时关闭旧套接字,你也可以明确地告诉它这样做

添加适当的 HTTP 头可以解决这两个问题。因此,消息部分应该是这样的:

local message = { "HTTP/1.0 200 OK\r\nServer: NodeMCU on ESP8266\r\nConnection: close\r\nContent-Type: text/html\r\n\r\n" }

counter = counter + 1

message[#message + 1] = "<html><head> <meta http-equiv=refresh content=1; URL=http://" .. own_ip .. "> </head>"
message[#message + 1] = "<body><h1> ESP8266 SHT-31 Web Server Ver 003</h1>"
message[#message + 1] = "<h2>some more text blabla blub" .. counter .. "</h2></body></html>"

注意 Connection: closeContent-Type: text/html,以及正确结构化的 HTML 标记。

2017-09-18 20:15:44