luaesp8266nodemcu

NodeMCU HTTP server stops responding


I'm trying to make a simple HTTP server with NodeMCU. I start up nodeMCU then connect it to the wifi and then run the program below. I can connect to the server from my browser. If I keep on reloading the page it would work forever, but when I stop sending requests for a minute or two, the server will somehow stop functioning. Which means, when I reload page nodeMCU does not receive any data (and cannot return any data back).

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>Since the start of the server " .. a .. " connections were made</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)

Some things I did:

I'm running precompiled firmware 0.9.6-dev_20150704 integer.

Edit: A solution burried in the comments below

The problem was some sort of incompatiblity between my AP and NodeMCU. To keep NodeMCU responding, I had to keep pinging it from my computer.


Solution

  • First of all, you shouldn't use those old 0.9.x binaries. They're no longer supported and contain lots of bugs. Build a custom firmware from the dev (1.5.1) or master (1.4) branch: http://nodemcu.readthedocs.io/en/dev/en/build/.

    With version >1.0 of the SDK (this is what you get if you build from current branches) conn:send is fully asynchronous i.e. you can't call it multiple consecutive times. Also, you must not call conn:close() right after conn:send() as the socket would possibly get closed before send() is finished. Instead you can listen to the sent event and close the socket in its callback. Your code works fine on an up-to-date firmware if you consider this.

    A more elegant way of asynchronous sending is documented in the NodeMCU API docs for socket:send(). However, that method uses more heap and is not necessary for simple cases with little data like yours.

    So, here's the full example with on("sent"). Note that I changed the favicon to an external resource. If you use "/" the browser still issues an extra request against your 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)