2016-03-18 49 views
4

我一直在閱讀NodeMCU文檔以及有關SDK的更改的幾個封閉問題,這些問題以前可以發送多個數據流排隊的net.socket:發送)。如何使用新的SDK(NodeMCU)發送多個數據(conn:send())

這裏似乎有一個巨大的爭論(#730)和那裏(#993)甚至在這裏(#999)。然而,我沒有找到一個令人信服的web服務器代碼示例,它允許我讀取多個html文件(例如head.htmlbody.html)以顯示頁面。下面是從TerryE的例子中,我試圖去適應,但沒有成功:

srv=net.createServer(net.TCP) 
srv:listen(80,function(conn) 
    conn:on ("receive", function(sck, req) 
     local response = {} 

     local f = file.open("head.html","r") 
     if f ~= nil then 
      response[#response+1] = file.read() 
      file.close() 
     end 

     local f = file.open("body.html","r") 
     if f ~= nil then 
      response[#response+1] = file.read() 
      file.close() 
     end 

     local function sender (sck) 
      if #response>0 then sck:send(table.remove(response,1)) 
      else sck:close() 
      end 
     end 
     sck:on("sent", sender) 
     sender(sck) 
    end) 
end) 

當連接到ESP8266,沒有加載和我從LUA終端沒有錯誤。

爲了您的信息,head.html包含:

<html> 
<head> 
</head> 

而且body.html包含:

<body> 
<h1>Hello World</h1> 
</body> 
</html> 

我是很新的NodeMCU,請寬容。

回答

1

謝謝你的回覆。我實際上添加了你提到的標題,我不知道這是必要的,並且我還刪除了sender函數中的sck參數。我的第一個代碼實際上是工作的,我不知道上次有什麼錯誤。

不管怎樣,它幫助我瞭解發生了什麼事:下面的代碼似乎來串聯response陣列,因爲插座的情況下sent回調的sender功能(sck:on("sent", sender)

sck:send(table.remove(response,1)) 

事實上,table.remove(array, 1)返回數組的第一個項目,並刪除該數組的這個項目。多次調用此行可以逐項讀取它。

爲了簡單起見,這裏是一個簡單Web服務器的代碼能夠服務於多個文件:

header = "HTTP/1.0 200 OK\r\nServer: NodeMCU on ESP8266\r\nContent-Type: text/html\r\n\r\n" 
srv=net.createServer(net.TCP) 
srv:listen(80,function(conn) 
    conn:on ("receive", function(sck, req) 
     local response = {header} 

     tgtfile = string.sub(req,string.find(req,"GET /") +5,string.find(req,"HTTP/") -2) 
     if tgtfile == "" then tgtfile = "index.htm" end 
     local f = file.open(tgtfile,"r") 
     if f ~= nil then 
      response[#response+1] = file.read() 
      file.close() 
     else 
      response[#response+1] = "<html>" 
      response[#response+1] = tgtfile.." not Found - 404 error." 
      response[#response+1] = "<a href='index.htm'>Home</a>" 
     end 
     collectgarbage() 
     f = nil 
     tgtfile = nil 

     local function sender() 
      if #response>0 then sck:send(table.remove(response,1)) 
      else sck:close() 
      end 
     end 
     sck:on("sent", sender) 
     sender() 
    end) 
end) 

這個例子是從這個instructables採取固定與新SDK的工作(這不允許多個:發送)。請讓我知道這個代碼是否有問題。

雖然我不知道文件的大小限制是什麼。儘管如此,我仍然設法在response變量中添加超過2Ko的數據,並立即發送,沒有任何問題。

+0

特里的最初的例子的美妙之處在於它與一個隱含的循環回調,如你所述。它從表中取出一塊(請不要稱爲數組),發送它並在發送回調時再次調用發送方以發送下一個表,直到表爲空。您的代碼唯一的主要問題是,無論實際內容如何,​​您都會發送相同的HTTP標頭。在'file == nil'的情況下,你的頭文件應該報告HTTP 404而不是HTTP 200.因此,而不是在第5行添加'header',你應該在if/else內有條件地做。 –

+0

另外,http://lua-users.org/wiki/LuaStyleGuide-> Lua Idioms,你可以使用'if then then'來代替'if if〜then then'。就我個人而言,我從來不會調用變量'f',因爲我喜歡錶達性的名字,但這是一個風格問題。 –

+0

我的主要附錄是值得Lua的額外幾十行在響應數組中查看並計算最大espconn緩衝區大小中的多少個數,然後將前N個緩衝區編組爲單個發送數據,例如, 'SCK:發送(table.concat({解包(響應,1,N)}))'。這可能看起來很笨重,但是大部分這個clunk都是在直接從C編譯的代碼中執行的,因此運行效率非常高,並且提供了很好的數據包大小。 – TerryE

3

這裏是不使用表,節省了一些內存我的解決方案:

function Sendfile(sck, filename, sentCallback) 
    if not file.open(filename, "r") then 
     sck:close() 
     return 
    end 
    local function sendChunk() 
     local line = file.read(512) 
     if line then 
      sck:send(line, sendChunk) 
     else 
      file.close() 
      collectgarbage() 
      if sentCallback then 
       sentCallback() 
      else 
       sck:close() 
      end 
     end 
    end 
    sendChunk() 
end 


srv = net.createServer(net.TCP) 
srv:listen(80, function(conn) 
    conn:on("receive", function(sck, req) 
     sck:send("HTTP/1.1 200 OK\r\n" .. 
      "Server: NodeMCU on ESP8266\r\n" .. 
      "Content-Type: text/html; charset=UTF-8\r\n\r\n", 
      function() 
       Sendfile(sck, "head.html", function() Sendfile(sck, "body.html") end) 
      end)   
    end) 
end) 

這是服務單個文件:

function Sendfile(client, filename) 
    if file.open(filename, "r") then 
     local function sendChunk() 
      local line = file.read(512) 
      if line then 
       client:send(line, sendChunk) 
      else 
       file.close() 
       client:close() 
       collectgarbage() 
      end 
     end 
     client:send("HTTP/1.1 200 OK\r\n" .. 
      "Server: NodeMCU on ESP8266\r\n" .. 
      "Content-Type: text/html; charset=UTF-8\r\n\r\n", sendChunk) 
    else 
     client:send("HTTP/1.0 404 Not Found\r\n\r\nPage not found") 
     client:close() 
    end 
end 


srv = net.createServer(net.TCP) 
srv:listen(80, function(conn) 
    conn:on ("receive", function(client, request) 
     local path = string.match(request, "GET /(.+) HTTP") 
     if path == "" then path = "index.htm" end 
     Sendfile(client, path) 
    end) 
end) 
相關問題