2011-04-26 102 views
11

我正在编写一个使用Lua套接字与http服务器进行通信的程序。 我使用的API是“socket.http.request”,我发现它是同步的。我的理解是,它会一直等到它得到一些响应或超时。 我的理解是否正确?如果是这样,我宁愿使用异步API。Lua套接字异步调用

我还发现了另一个API“socket.http.request_cb”,它在处理请求时调用回调函数。但是,这似乎并没有在这里工作。 (这个API在我使用的版本上不可用。)我在这里使用Lua 5.1和Lua套接字2.0.2。任何人都可以让我知道哪个版本的Lua或Lua套接字具有此API?

+0

[Luasocket问题]的可能重复(http://stackoverflow.com/questions/5416082/problem-with-luasocket) – finnw 2011-04-28 00:02:45

回答

10

使用连接:settimeout(),您可以为连接设置超时。这是在为lua插座并行下载的这个例子中使用:

function download (host, file, port) 
    port = port or 80 
    print (host, file, port)  
    local connectStatus, myConnection = pcall (socket.connect,host,port) 
    if (connectStatus) then 
     myConnection:settimeout(0.01) -- do not block you can play with this value 
     local count = 0 -- counts number of bytes read 
     -- May be easier to do this LuaSocket's HTTP functions 
     myConnection:send("GET " .. file .. " HTTP/1.0\r\n\r\n") 
     local lastStatus = nil 
     while true do 
      local buffer, status, overflow = receive(myConnection, lastStatus) 
      -- If buffer is not null the call was a success (changed in LuaSocket 2.0) 
      if (buffer ~= nil) then 
       io.write("+") 
       io.flush() 
       count = count + string.len(buffer) 
      else 
       print ("\n\"" .. status .. "\" with " .. string.len(overflow) .. " bytes of " .. file) 
       io.flush() 
       count = count + string.len(overflow) 
      end 
      if status == "closed" then break end 
       lastStatus=status 
      end 
     myConnection:close() 
     print(file, count) 
    else 
     print("Connection failed with error : " .. myConnection) 
     io.flush() 
    end 
end 

threads = {} -- list of all live threads 

function get (host, file, port) 
    -- create coroutine 
    local co = coroutine.create(
     function() 
      download(host, file, port) 
     end) 
    -- insert it in the 
    table.insert(threads, co) 
end 

function receive (myConnection, status) 
    if status == "timeout" then 
     print (myConnection, "Yielding to dispatcher") 
     io.flush() 
     coroutine.yield(myConnection) 
    end 
    return myConnection:receive(1024) 
end 

function dispatcher() 
    while true do 
     local n = table.getn(threads) 
     if n == 0 then break end -- no more threads to run 
     local connections = {} 
     for i=1,n do 
      print (threads[i], "Resuming") 
      io.flush() 
      local status, res = coroutine.resume(threads[i]) 
      if not res then -- thread finished its task? 
       table.remove(threads, i) 
       break 
      else -- timeout 
       table.insert(connections, res) 
      end 
     end 
     if table.getn(connections) == n then 
      socket.select(connections) 
     end 
    end 
end 

host = "www.w3.org" 
get(host, "/TR/html401/html40.txt") 
get(host,"/TR/2002/REC-xhtml1-20020801/xhtml1.pdf") 
get(host,"/TR/REC-html32.html") 
get(host,"/TR/2000/REC-DOM-Level-2-Core-20001113/DOM2-Core.txt") 
dispatcher() 
1

我做的所有IO复用的东西与lua-ev。它是一个类似于node.js之后的事件循环实现。一个线程,没有比赛。