Pessoal, já utilizei a classe tcp disponibilizada pelo Francisco algumas vezes sem problemas. Porém, gostaria de criar uma função para enviar uma requisição GET a uma página e obter o HTML retornado.
Sem criar tal função, o código para tal fim ficaria como:
local content = ""
tcp.execute(
function ()
tcp.connect(host, 80)
local url = "GET "..uri.." HTTP/1.0\n"
tcp.send(url)
content = tcp.receive("*a")
if content then
createFile(content, fileName)
end
tcp.disconnect()
end
)
Veja que dentro do if, se foi retornando algum conteúdo, o mesmo é salvo em um arquivo.
Porém, gostaria de criar uma função como:
function getWebPage(host, uri)
local content = nil
tcp.execute(
function ()
tcp.connect(host, 80)
local url = "GET "..uri.." HTTP/1.0\n"
tcp.send(url)
content = tcp.receive("*a")
tcp.disconnect()
end
)
return content --por algum motivo, nunca chega aqui
end
Desta forma, bastaria chamá-la como:
local content = getWebPage(host, uri) --a função nunca retorna
--O if/else abaixo nunca é executado, pois getWebPage
--nunca retorna
if content then
createFile(content, fileName)
else
print("Nenhum conteúdo foi retornado")
end
Porém, desta forma, a função getWebPage nunca retorna, não chegando nunca na linha do if.
A vantagem de utilizar uma função como a getWebPage é que esconde toda a complexidade das chamadas da classe TCP.
Analisei todo o código do arquivo tcp.lua mas não consegui entender o motivo disso. Compreendo como funcionam as funções de co-rotinas, mas não encontrei o motivo de tcp.execute nunca retornar para quem o chamou.
Autor: Manoel Campos da Silva Filho
44 comentários
local content = nil
local co = false
--body function da co-rotina co
function f()
tcp.execute(
function ()
tcp.connect(host, 80)
local url = "GET "..uri.." HTTP/1.0\n"
tcp.send(url)
--somente aqui que o retorno da função getWebPage é obtido
content = tcp.receive("*a")
tcp.disconnect()
--só continua a execução da co-rotina depois
--que a conexão for fechada (na linha acima)
coroutine.resume(co)
end
)
--após a execução de tcp.execute (que retorna imediatamente),
--suspende a execução da co-rotina
coroutine.yield()
end --cria uma co-rotina para executar todo o
--da body function f
co = coroutine.create(f) --inicia a co-rotinas, mas pelo que vi, o resume retorna imediatamente,
--sendo que seria necessário que aguardasse até a conexão tcp ser fechada
coroutine.resume(co) --retorna o conteúdo obtido dentro da função anônima
--passada a tcp.execute
return content
end
--@param imageUrl URL da imagem a ser baixada
--@param _callback Função de callback a ser
--executada quando a imagem for obtida do servidor web.
local function getImage(imageUrl, _callback)
if http.getFile(imageUrl, fileName) then
--Após baixar a imagem, chama a função de callback p/ exibir a mesma
_callback()
end
end --Função de callback a ser
--executada quando a imagem for obtida do servidor,
--para exibir a mesma na tela.
local function showImageCallback()
local img = canvas:new(fileName)
canvas:compose(1, 1, img)
canvas:flush()
end --Cria uma co-rotina para executar a função getImage, definida acima.
--O parâmetro showImageCallback é uma função de callback
--que será chamada quando getImage retornar, tendo concluído o download da imagem.
util.coroutineCreate(getImage, showImageCallback)