lua协程

这里介绍一个lua实现多协程下载文件的例子(来源是lua程序设计第四版, 下载链接请私信我, 免费给,csdn传过一次,没通过 )
协程的精髓就在于coroutine.resume的时候从主线程把数据传递给协程(如果是第一次执行,则作为执行函数的参数,之后再执行则作为yield的返回值赋值给上次停止执行的位置的变量), 而执行到coroutine.yield的时候又可以把协程内的数据传递到主线程

1.依赖于luasocket,需要下载编译

  • 1.下载源码 git clone https://github.com/diegonehab/luasocket.git
  • 2.修改lua版本并编译安装
cd luasocket/src
vi makefile # 将默认的5.1改为你的lua版本
make linux & make install
  • 3.验证, 命令中输入lua, 进入lua交互界面, 输入require “socket”,不报错就ok

2.串行下载

local socket = require('socket')

function receive(conn)
    local s, status, partial = conn:receive(2^10)
    return s or partial, status
end

function getMsTime( )
    local  now = socket.gettime() * 1000
    local tmp1, _ = math.modf(now)
    return tmp1
end

function download(host, file)
    local startClock = getMsTime()
    local c = assert(socket.connect(host, 80))
    local count = 0
    local request = string.format("GET %s HTTP/1.0\r\nhost: %s \r\n\r\n", file, host)
    c:send(request)
    while true do
        local s, status = receive(c)
        count = count + #s
        if status == "closed" then
            break
        end
    end
    c:close()
    local endClock = getMsTime()
    print(string.format("file: %s, size: %d, cost: %dms", file, count, endClock - startClock))
end

-- 串行下载文件
local startClock = getMsTime()
print("start download...")
download("www.lua.org", "/ftp/lua-5.3.2.tar.gz")
download("www.lua.org", "/ftp/lua-5.3.1.tar.gz")
download("www.lua.org", "/ftp/lua-5.3.0.tar.gz")
local endClock = getMsTime()
print(string.format("finish download... total cost: %dms ", endClock - startClock))

多协程下载

local socket = require('socket')

function receive(conn)
    conn:settimeout(0) -- 设置为非阻塞模式
    local s, status, partial = conn:receive(2^10)
    if status == "timeout" then
        coroutine.yield(conn) -- 把当前的connection传出去
    end
    return s or partial, status
end

tasks = {}
logfile= io.open("./test.txt","w+")
io.output(logfile)

-- coroutine.wrap和coroutine.create 区别
-- 1.warp调用简单,直接co(param)执行就行,缺点,返回值只有一个(yield返回的值),无法直接从返回值中获取协程的状态
-- 2.create创建的需要配合resume执行,local r1, r2 = coroutine.resume(co, param) r1为布尔值代表执行是否成功,r2为yield返回的值
function corDownload (host, file)
    -- 为任务创建协程
    local co = coroutine.wrap(function ()
        download(host, file)
    end)
    -- local co = coroutine.create(function ()
    --     download(host, file)
    -- end)

    -- 将任务插入列表
    table.insert(tasks, co)
end

-- 协程调度,当执行的的协程返回时,调度另一个协程进行执行,直到所有协程执行结束退出循环
function dispatch ()
    local i = 1
    while true do 
        if tasks[i] == nil then 
            if tasks[1] == nil then
                break
            end
            i = 1
        end
        local res = tasks[i]() -- 执行一个任务
        --local _, res = coroutine.resume(tasks[i]) -- 执行一个任务
        if not res then
            table.remove(tasks, i)
        else
            i = i + 1
        end
    end
end

-- 使用LuaSocket的select,所有协程都没有数据时进入忙等待状态
function dispatchWithSelect ()
    local i = 1
    timeout = {}
    while true do 
        if tasks[i] == nil then 
            if tasks[1] == nil then
                break
            end
            i = 1
            timeout = {}
        end
        local res = tasks[i]() -- 执行一个任务
        --local _, res = coroutine.resume(tasks[i]) -- 执行一个任务
        if not res then
            table.remove(tasks, i)
        else
            i = i + 1
            timeout[#timeout + 1] = res
            if #timeout == #tasks then -- 所有任务都阻塞
                socket.select(timeout)
            end
        end
    end
end

function getMsTime( )
    local  now = socket.gettime() * 1000
    local tmp1, _ = math.modf(now)
    return tmp1
end



function download(host, file)
    local startClock = getMsTime()
    local c = assert(socket.connect(host, 80))
    local count = 0
    local request = string.format("GET %s HTTP/1.0\r\nhost: %s \r\n\r\n", file, host)
    c:send(request)
    while true do
        local s, status = receive(c)
        if status == nil then
            status = "nil"
        end
        io.write(status .. "\n")
        count = count + #s
        if status == "closed" then
            break
        end
    end
    c:close()
    local endClock = getMsTime()
    print(string.format("file: %s, size: %d, cost: %dms", file, count, endClock - startClock))
end


local startClock = getMsTime()
print("start download...")
corDownload("www.lua.org", "/ftp/lua-5.3.2.tar.gz")
corDownload("www.lua.org", "/ftp/lua-5.3.1.tar.gz")
corDownload("www.lua.org", "/ftp/lua-5.3.0.tar.gz")
dispatch()
local endClock = getMsTime()
print(string.format("finish download... total cost: %dms ", endClock - startClock))



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值