Lua 非抢先式的(non-preemptive)多线程
177
2017-07-15
依赖
- LuaSocket 库
- 使用HTTP下载远程文件实例
LuaSocket实现文件下载
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()
- 0
- 0
-
分享