Lua socket 异步调用。

我正在编写一个使用Lua socket与http服务器通信的程序。 我使用的API是"socket.http.request",我发现它是同步的。我的理解是它会等待直到收到响应或超时。 我的理解是否正确?如果是,我更喜欢使用异步API。

我还发现另一个API"socket.http.request_cb",它在处理请求时调用回调函数。但它在这里似乎无效。(我使用的版本中没有这个API。)我这里使用的是Lua 5.1和Lua socket 2.0.2。有人能告诉我哪个版本的Lua或Lua socket有这个API吗?

原文链接 https://stackoverflow.com/questions/5795419

点赞
stackoverflow用户513763
stackoverflow用户513763

使用connection:settimeout(),可以为连接设置超时时间。在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) -- 不阻塞,可以尝试不同的值
        local count = 0 -- 统计已读取的字节数
        -- 或者使用LuaSocket的HTTP函数更容易
        myConnection:send("GET " .. file .. " HTTP/1.0\r\n\r\n")
        local lastStatus = nil
        while true do
            local buffer, status, overflow = receive(myConnection, lastStatus)
            -- 如果buffer不为nil,则调用成功(在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 = {} -- 所有线程的列表

function get (host, file, port)
    -- 创建协程
    local co = coroutine.create(
        function ()
            download(host, file, port)
        end)
    -- 将协程插入列表中
    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 -- 没有线程需要运行
        local connections = {}
        for i=1,n do
            print (threads[i], "Resuming")
            io.flush()
            local status, res = coroutine.resume(threads[i])
            if not res then -- 线程已经完成了任务?
                table.remove(threads, i)
                break
            else -- 超时
                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()
2011-04-27 19:38:52
stackoverflow用户33252
stackoverflow用户33252

你可能会在luaThread中找到灵感。其中之一的演示是一个异步的wget

最近开发的线程库lua-llthreads支持ZMQ“作为并发框架的套接字库”lua-zmq

2011-04-28 15:00:43
stackoverflow用户1358661
stackoverflow用户1358661

我使用lua-ev来做所有的IO多路复用。它是一个类似于node.js的事件循环实现。只有一个线程,不存在竞争。

2013-11-05 22:42:55