• 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
    
    • 1
    • 2
    • 3
    • 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))
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    多协程下载

    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))
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
  • 相关阅读:
    蓝桥杯第十四届电子类单片机组决赛程序设计
    Waline评论服务docker自部署手册 + 无需备案域名配置
    为什么Proteus串口无法正常显示
    14届蓝桥青少STEMA-C++组10月评测
    UNI-APP apk使用io流进行文件操作
    抖音矩阵系统。抖音矩阵系统。抖音矩阵系统。抖音矩阵系统。
    基于不同监督强度分类的语义分割综述:A Breif Survey on Semantic Segmentation with Deep Learning
    使用 PowerShell和工具软件在 Windows 中更改文件时间戳
    《大话设计模式》精髓理解——Chapter 16 - 20 状态、适配器、备忘录、组合、迭代器
    OSI网络模型与TCP/IP协议
  • 原文地址:https://blog.csdn.net/blake321/article/details/126880645