2011-04-26 75 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之後的事件循環實現。一個線程,沒有比賽。