问题
I am writing a program that uses Lua socket to communicate with a http server. The API that I am using is "socket.http.request", and I have found that it is synchronous. My understanding is that it waits until it gets some response or time outs. Is my understanding correct? If so, I'd prefer to use an asynchronous API.
I also found another API "socket.http.request_cb", which calls a call back function when the request is processed. However, it doesn't seem to work here. (This API is not available on the version that I'm using.) I'm using Lua 5.1 and Lua socket 2.0.2 here. Could anyone let me know which version of Lua or Lua socket has this API?
回答1:
With connection:settimeout() you can set a time out for a connection. This is used in this example of a parallel downloader for Lua Socket:
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()
回答2:
I am doing all IO multiplexing stuff with lua-ev. It an event loop implementation similar to the one behind node.js. One thread, no races.
回答3:
You may find some inspiration in luaThread. One of its demos is an asynchronous wget
.
A recently developed threading library lua-llthreads supports the ZMQ "socket library that acts as a concurrency framework" with lua-zmq
来源:https://stackoverflow.com/questions/5795419/lua-socket-asynchronous-calls