非搶先式的(non-preemptive)多線程
LuaSocket 庫
-
使用HTTP下載遠程文件實例
- lua socket 實現文件下載
require "socket" -- 加載 LuaSocket host = "www.w3.org" -- 定義主機 file = "/Help/Webmaster.html" -- 下載的文件 c = assert(socket.connect(host,80)) -- 鏈接到該站點的80端口 c:send("GET " .. file .. " HTTP/1.0\r\n\r\n") -- 發送文件請求 while true do local s, status, partial = c:receive(2^10) io.write(s or partial ) if status == "closed" then break end end c:close()
- 多線程下載
require "socket" function download(host , file ) local c = assert(socket.connect( host , 80)) local count = 0 -- 記錄接收到的字節數 c:send("GET " .. file .. " HTTP/1.0\r\n\r\n") while true do local s,status,partial = receive(c) count = count + #( s or partial) if status == "closed" then break end end io.write("文件下載完成,大小: " .. count .. "\n" ) end -- 順序下載 function receive(connection) return connection:receive(2^10) end -- 并發下載 function receive(connection) connection:settimeout(0) -- 使用receive調用不會堵塞 local s , status , partial = connection:receive(2^10) if status == "timeout" then coroutine.yield(connection) end return s or partial , status end threads = {} -- 用于記錄所有正在運行的線程 function get( host , file ) -- 創建協同程序 local co = coroutine.create( function() download(host,file) end ) table.insert(threads,co) end function dispatch() local i = 1 while true do if threads[i] == nil then -- 還有線程嗎? if threads[1] == nil then -- 判斷列表是否為空 break end i = 1 end local status , res = coroutine.resume(threads[i]) if not res then table.remove(threads,i) else i = i + 1 end end end host = "www.w3.org" -- 定義主機 file1 = "/standards/webofservices/" -- 下載的文件 file2 = "/Help/Webmaster.html" -- 下載的文件 file3 = "/participate/" -- 下載的文件 get(host , file1) get(host , file2) get(host , file3) dispatch()
- 實現多線程下載 (假如超時處理邏輯)
require "socket" function download(host , file ) local c = assert(socket.connect( host , 80)) local count = 0 -- 記錄接收到的字節數 c:send("GET " .. file .. " HTTP/1.0\r\n\r\n") while true do local s,status,partial = receive(c) count = count + #( s or partial) if status == "closed" then break end end io.write("文件下載完成,大小: " .. count .. "\n" ) end -- 順序下載 function receive(connection) return connection:receive(2^10) end -- 并發下載 function receive(connection) connection:settimeout(0) -- 使用receive調用不會堵塞 local s , status , partial = connection:receive(2^10) if status == "timeout" then coroutine.yield(connection) end return s or partial , status end threads = {} -- 用于記錄所有正在運行的線程 function get( host , file ) -- 創建協同程序 local co = coroutine.create( function() download(host,file) end ) table.insert(threads,co) end function dispatch() local i = 1 while true do if threads[i] == nil then -- 還有線程嗎? if threads[1] == nil then -- 判斷列表是否為空 break end i = 1 -- 重新開始循環 end local status , res = coroutine.resume(threads[i]) if not res then table.remove(threads,i) else -- 超時 i = i + 1 if connections==nil then connections = {} -- connections 用來存放當前超時的 線程 connections[1] = res else connections[#connections + 1 ] = res if #connections == #threads then -- 所有線程都堵塞了 socket.select(connections) end end end end end host = "www.w3.org" -- 定義主機 file1 = "/standards/webofservices/" -- 下載的文件 file2 = "/Help/Webmaster.html" -- 下載的文件 file3 = "/participate/" -- 下載的文?
?
get(host , file1)
get(host , file2)
get(host , file3)
dispatch()