我想下载一个大文件并同时处理其他事情。
但是,luasocket.http
从不致电coroutine.yield()
。文件下载时,其他所有内容都会冻结。
这是一个说明性示例,我尝试同时下载文件并打印一些数字:
local http = require'socket.http'
local downloadRoutine = coroutine.create(function ()
print 'Downloading large file'
-- Download an example file
local url = 'http://ipv4.download.thinkbroadband.com/5MB.zip'
local result, status = http.request(url)
print('FINISHED download ('..status..', '..#result..'bytes)')
end)
local printRoutine = coroutine.create(function ()
-- Print some numbers
for i=1,10 do
print(i)
coroutine.yield()
end
print 'FINISHED printing numbers'
end)
repeat
local printActive = coroutine.resume(printRoutine)
local downloadActive = coroutine.resume(downloadRoutine)
until not downloadActive and not printActive
print 'Both done!'
运行它会产生这个:
1
Downloading large file
FINISHED download (200, 5242880bytes)
2
3
4
5
6
7
8
9
10
FINISHED printing numbers
Both done!
如您所见,printRoutine
首先是resume
。它打印数字1和yield
s。然后downloadRoutine
为resume
d,下载整个文件,而不会产生。只有这样才能打印其余数字。
我不想写自己的套接字库!我该怎么办?
编辑(当天晚些时候):部分MUSH用户have also noticed。他们提供有用的想法。
答案 0 :(得分:5)
我不明白为什么你不能使用PiL advice或copas library(这几乎与here给出的答案相同)。
Copas包装套接字接口(不是socket.http
),但您可以使用低级接口来获取所需内容(未经测试):
require("socket")
local conn = socket.tcp()
conn:connect("ipv4.download.thinkbroadband.com", 80)
conn:send("GET /5MB.zip HTTP/1.1\n\n")
local file, err = conn:receive()
print(err or file)
conn:close()
然后,您可以使用来自copas的addthread
为您提供一个非阻塞套接字,并使用step/loop
函数执行receive
,同时接收内容。
使用copas的工作量较少,而直接使用settimeout(0)
可以让您获得更多控制权。
答案 1 :(得分:2)
协同程序不是线程;他们是合作的,而不是同时的。当一个协程从另一个协同程序产生时,它会被阻塞。你不能在vanilla Lua中同时拥有两个执行指针。
但是,您可以使用外部库来实现此目的。其中最受欢迎的是Lua Lanes。