-
Notifications
You must be signed in to change notification settings - Fork 0
/
mthread.lua
70 lines (64 loc) · 1.73 KB
/
mthread.lua
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
socket = require("socket")
host = "www.lua.org"
file = "/manual/5.3/manual.html"
function download (host, file, fp, port)
local c = assert(socket.connect(host, port or 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)
local current
if fp then current = fp:seek() end
repeat
local s, status, partial = receive(c)
count = count + #s
-- 断点续传
if fp then
fp:seek("end")
fp:write(s or partial)
fp:flush()
end
until status == "closed"
if fp then fp:seek("set", current) end
c:close()
io.write(file, count)
end
function receive (connection)
connection:settimeout(0)
local s, status, partial = connection:receive(2^10)
if status == "timeout" then
coroutine.yield(connection)
-- io.write("\r\n[COROUTINE RESUMED] " .. (s or partial))
end
return s or partial, status
end
tasks = {}
function get (host, file, fp, port)
local co = coroutine.wrap(function ()
download(host, file, fp, port)
end)
table.insert(tasks, co)
end
function runall ()
local i = 1
local timedout = {}
while true do
if tasks[i] == nil then
if tasks[1] == nil then
break
end
i = 1
timedout = {}
end
local res = tasks[i]()
if not res then
table.remove(tasks,i)
else
i = i + 1
timedout[#timedout + 1] = res
if #timedout == #tasks then
socket.select(timedout)
end
end
end
end