NodeMCU HTTP服务器停止响应

我正在尝试用NodeMCU制作一个简单的HTTP服务器。我启动NodeMCU,然后连接到WiFi,然后运行下面的程序。我可以从浏览器连接到服务器。如果我一直重载页面,它可以一直工作,但是如果停止发送请求一两分钟,服务器将会停止工作。这意味着,当我重新加载页面时,NodeMCU不会收到任何数据(也无法返回任何数据)。

a=0

function receive(conn,payload)
    a=a+1
    print(payload)

    local content="<!DOCTYPE html><html><head><link rel='shortcut icon' href='/'></head><body><h1>Hello!</h1><p>自服务器启动以来,已进行了" .. a .. "个连接</p></body></html>"
    local contentLength=string.len(content)

    conn:send("HTTP/1.1 200 OK\r\nContent-Length:" .. contentLength .. "\r\n\r\n" .. content)
    conn:close()
end

function connection(conn)
    conn:on("receive",receive)
end

srv=net.createServer(net.TCP,1)
srv:listen(8080,connection)

我做了一些事情:

  • 我停止了浏览器通过添加到无处链接的favicon请求。
  • 我将空闲客户端的超时时间设置为1,以防止浏览器长时间加载(浏览器会一直加载直到超时)。
  • 我更新了代码以发送一些HTTP头。
  • 我尝试在每次连接后关闭和打开服务器(无益,因为即使没有这个修复措施,如果你一直做连接,它也不会停止工作)。
  • 我像StackOverflow上的一个答案建议的那样添加了conn:close()

我正在运行预编译的固件0.9.6-dev_20150704整数。

点赞
用户131929
用户131929

首先,你不应该使用那些旧的 0.9.x 二进制文件。它们已不再受支持,并且存在很多错误。从 dev (1.5.1) 或 master (1.4) 分支中构建自定义固件:http://nodemcu.readthedocs.io/en/dev/en/build/

SDK 版本 >1.0(如果你从当前分支构建,则会得到此版本)中,conn:send 是完全异步的,即你不能连续多次调用它。此外,你不能在 conn:send() 后立即调用 conn:close(),因为在 send() 完成之前套接字可能会被关闭。相反,你可以在其回调中监听 sent 事件并关闭套接字。如果你考虑到了这点,你的代码在更新的固件上可以正常工作。

针对异步发送的更优雅的方法已经在 NodeMCU API 文档 的 socket:send() 中记录。然而,该方法使用了更多的堆,对于像你这样数据较少的简单情况并不是必需的。

所以,这里是一个使用 on("sent") 的完整示例。请注意,我将 favicon 改为了外部资源。如果你使用 "/",浏览器仍会针对你的 ESP8266 发出额外的请求。

a = 0

function receive(conn, payload)
    print(payload)
    a = a + 1

    local content="<!DOCTYPE html><html><head><link rel='icon' type='image/png' href='http://nodemcu.com/favicon.png' /></head><body><h1>Hello!</h1><p>Since the start of the server " .. a .. " connections were made</p></body></html>"
    local contentLength=string.len(content)

    conn:on("sent", function(sck) sck:close() end)
    conn:send("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length:" .. contentLength .. "\r\n\r\n" .. content)
end

function connection(conn)
    conn:on("receive", receive)
end

srv=net.createServer(net.TCP, 1)
srv:listen(8080, connection)
2016-05-01 21:39:16