ПАНИКА: незащищенная ошибка при вызове Lua API (wificonfig.lua:33: адрес используется)

Я пытаюсь создать локальный http-сервер на ESP8266 с помощью lua, используя пользовательскую сборку NodeMCU от frightanic.com.

Когда я создаю локальный http-сервер вместе с соединением, которое уже прослушивает порт 80 и извлекает данные с моего сервера, это дает мне ошибку PANIC.

Вот мой код:

wifi.setmode(wifi.STATION)
wifi.sta.config("SSID","password")
wifi.sta.connect()

tmr.alarm(1,10000, 1, function()
    if (wifi.sta.getip() == nil) then
        print("IP unavaiable, Waiting...")
    else
        foo()
        local_server()
    end
end)


function foo()
        conn = nil
        conn=net.createConnection(net.TCP,0)
        conn:on("receive", function(conn, payload)
            print("payload : "..#payload);
        end)
        conn:connect(80,"server.co.in")
        conn:on("connection", function(conn, payload)
            conn:send("GET /mypage?id=deadbeef HTTP/1.0\r\nHost: server.co.in\r\nConnection: keep-alive\r\nAccept: */*\r\n\r\n") end)

        conn:on("sent",function(conn)
                print("Closing server connection")
                conn:close()
            end)
end

function local_server()
    srv=net.createServer(net.TCP)
    srv:listen(80,function(conn)
        conn:on("receive", function(client,request)
            local buf = "Hello world";
            client:send('HTTP/1.0\n\n')
            client:send('<!DOCTYPE HTML>\n')
            client:send('<html>\n')
            client:send('<head><meta  content="text/html; charset=utf-8">\n')
            client:send('<title>Local server</title></head>\n')
            client:send('<style>body{ background-color: #cccccc; font-family: Arial, Helvetica, Sans-Serif; Color: #000088; }</style>\n";')
            client:send(buf);

            conn:on("sent",function(conn)
                srv:close() -- Even tried with client:close()
            end)
        end)
    end)

end

Разве это невозможно сделать? Если да, то как я могу это сделать?

Если я создаю сервер один раз внутри таймера, он не создает никакого локального сервера, т.е. я не могу открыть свой локальный сервер 192.168.xy.

Вот мой модифицированный код:

wifi.setmode(wifi.STATION)
wifi.sta.config("SSID","password")
wifi.sta.connect()

tmr.alarm(1,10000, 1, function()
    if (wifi.sta.getip() == nil) then
        print("IP unavaiable, Waiting...")
    else
        print("Creating a server");
        srv=net.createServer(net.TCP,0)
        srv:listen(80,function(conn) 
        end)
        tmr.stop(1)
        tmr.alarm(1,10000, 1, function() 
              foo()
              local_server()
        end)
    end
end)


function foo()
        conn = nil
        conn=net.createConnection(net.TCP,0)
        conn:on("receive", function(conn, payload)
            print("payload : "..#payload);
        end)
        conn:connect(80,"server.co.in")
        conn:on("connection", function(conn, payload)
            conn:send("GET /mypage?id=deadbeef HTTP/1.0\r\nHost: server.co.in\r\nConnection: keep-alive\r\nAccept: */*\r\n\r\n") end)

        conn:on("sent",function(conn)
                print("Closing server connection")
                conn:close()
            end)
end

function local_server()
        conn:on("receive", function(client,request)
            local buf = "Hello world";
            client:send('HTTP/1.0\n\n')
            client:send('<!DOCTYPE HTML>\n')
            client:send('<html>\n')
            client:send('<head><meta  content="text/html; charset=utf-8">\n')
            client:send('<title>Local server</title></head>\n')
            client:send('<style>body{ background-color: #cccccc; font-family: Arial, Helvetica, Sans-Serif; Color: #000088; }</style>\n";')
            client:send(buf);

            conn:on("sent",function(conn)
                srv:close() -- Even tried with client:close()
            end)
        end)
end

person aditgupta100    schedule 06.05.2017    source источник


Ответы (1)


        client:send('HTTP/1.0\n\n')

Это недопустимый HTTP-ответ. Как минимум ответ, обслуживающий HTML-страницу, должен выглядеть так

 HTTP/1.0 200 ok\r\n
 Content-type: text/html\r\n
 \r\n
 here comes the HTML body

Но это, вероятно, не причина для паники, так как он жалуется на используемый адрес. Я ничего не знаю об ОС, работающей на ESP8266, но обычно эта ошибка означает, что уже есть сокет, привязанный к этому адресу и порту, и что у вас не может быть другого в том же месте. Таким образом, если в этой системе уже запущен веб-сервер, вы не можете запустить другой веб-сервер по тому же адресу.

Такая ошибка также может произойти, если вы один раз успешно запустили сервер, не смогли установить связь (из-за неправильного HTTP-ответа вашего сервера), а затем снова попытались перезапустить сервер: потребуется некоторое время, прежде чем вы сможете повторно использовать один и тот же сокет один раз. к этому сокету было установлено соединение, поэтому вам может потребоваться подождать несколько минут перед повторным запуском сервера (или просто перезагрузить систему).

Присмотревшись к вашему коду, вы увидите, что сервер запускается изнутри таймера:

tmr.alarm(1,10000, 1, function()
...
        local_server()

Беглый взгляд на документацию по tmr выглядит как будто вы вызываете таймер с помощью tmr.ALARM_AUTO, чтобы он повторялся снова и снова. Это означает, что таймер будет повторяться после того, как вы уже настроили сервер и, таким образом, попытаетесь настроить сервер снова - на том же порту. Это вызывает ошибку используемого адреса.

person Steffen Ullrich    schedule 06.05.2017
comment
Сначала я использовал HTTP/1.0 200 ok, но когда это не сработало, я пытался использовать HTTP/1.0, потому что у меня мало знаний об этом. Адрес, на который указывает ошибка, является IP-адресом моего WiFi-модуля (работающего как станция, подключенная к точке доступа) или это какой-то другой адрес? Как вы можете видеть в моем коде, я открыл клиентское соединение через порт 80 с некоторым сервером, который я затем close.conn:connect(80,server.co.in) - person aditgupta100; 06.05.2017
comment
Я даже пытался слушать другой порт, скажем, 9999, но получал ту же ошибку. - person aditgupta100; 06.05.2017
comment
Сообщение об ошибке относится к локальному модулю WiFi. Я бы посоветовал вам сначала упростить свой код, т.е. реализовать только сервер и ничего больше. - person Steffen Ullrich; 06.05.2017
comment
foo() и local_server() отлично работают, если вызываются по отдельности, но если они оба вызываются внутри одного сценария lua, возникает эта ошибка, вероятно, потому, что он уже прослушивал порт 80 для локального http-сервера, и если я пытаюсь установить соединение на том же порту, чем выдает ошибку PANIC. Но я не знаю, как это исправить. - person aditgupta100; 07.05.2017
comment
@ aditgupta100: см. обновленный ответ: насколько я понимаю ваш код, вы настраиваете сервер несколько раз, потому что используете повторяющийся таймер. - person Steffen Ullrich; 07.05.2017
comment
даже я предполагал то же самое, но я не знаю, как решить проблему. Теперь я изменил код (см. обновленный код в вопросе), создав сервер только один раз... но теперь я не смог открыть локальный сервер 192.168.xy... Однако ошибки нет - person aditgupta100; 07.05.2017
comment
@aditgupta100: У меня такое ощущение, что вы просто возитесь с кодом, не понимая, что делаете. Нет смысла снова и снова настраивать обработчик приема на сервере. Кроме того: первоначальная проблема, с которой вы столкнулись (используемый адрес), объясняется и решается. Теперь у вас другая проблема, поэтому, пожалуйста, задайте новый вопрос. Это не дискуссионный сайт, и изменение вопроса, чтобы задать другой вопрос или задать новый вопрос внутри комментария, здесь не работает. - person Steffen Ullrich; 07.05.2017