2012-11-11 5 views
5

큰 파일을 다운로드하고 동시에 다른 것을 처리하고 싶습니다.coroutine.yield()가없는 루아 라이브러리를 어떻게 다룰 수 있습니까?

그러나 luasocket.httpcoroutine.yield()으로 전화하지 않습니다. 파일을 다운로드하는 동안 다른 모든 것들이 멈 춥니 다. 당신이 볼 수 있듯이

1 
Downloading large file 
FINISHED download (200, 5242880bytes) 
2 
3 
4 
5 
6 
7 
8 
9 
10 
FINISHED printing numbers 
Both done! 

printRoutineresume : 그것은이 생산 실행

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과 yield을 인쇄합니다. downloadRoutineresumed이며을 생성하지 않고 전체 파일 을 다운로드합니다. 그래야 나머지 숫자가 인쇄됩니다.

나 자신의 소켓 라이브러리를 쓰고 싶지 않습니다! 내가 무엇을 할 수 있을지?

편집 (나중에 같은 날) : 일부 암소 사용자 have also noticed. 그들은 유용한 아이디어를 제공합니다.

+1

코 루틴은 스레드가 아닙니다. 스레드처럼 취급해서는 안됩니다. 프로세스가 양보하기를 원하지 않는다면, 프로세스는 앞으로 나아 가지 않을 것이며, 프로세스가 양보 할 수도 없습니다. LuaSocket에는 비 차단 입출력을위한 몇 가지 기능이 있지만 LuaSocket에 익숙하지는 않으므로이를 조사해야합니다. –

+1

LuaSocket은 비동기 (즉, 비 차단) 작업을 지원합니다. 라이브러리를 다시 작성하기 전에 RTFM. – Mud

+3

진흙 : 그래, 원시'소켓'않습니다. 그러나'socket.http'는 그렇지 않습니다. (http://www.mail-archive.com/[email protected]/msg04969.html을보십시오.) – Anko

답변

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을 사용할 수 있습니다 비 블로킹 소켓을 제공하고 receive 할 함수가있는 step/loop 함수를 사용해야합니다.

copa를 사용하면 작업량이 적고 settimeout(0)을 사용하면 직접 제어 할 수 있습니다.

+0

유용한 대안을 제공해 주셔서 감사합니다! 내 구체적인 문제가 해결됩니다. My * question *은 좀 더 일반적입니다 : LuaSec의'ssl.https' (재 구현이 쉽지 않은)와 같은 다른 많은 라이브러리는 여전히 동기화되어 있습니다 ... – Anko

+0

좋은 점은 여전히 ​​동일 할 수도 있지만 ssl.https가있는 것.사실, 내가 준 예제는 ssl.https (http://notebook.kulchenko.com/programming/https-ssl-calls-with-lu-and-luasec)를 사용하여 예제를 단순화 한 것입니다. 그 말을 했더니,'ssl.https'가 settimeout (0)과 같은 방식으로 작동하는지 확실하지 않습니다. 테스트 할 기회가 없었기 때문입니다. –

2

코 루틴은 스레드가 아닙니다. 그들은 협동 적이지만 동시 적이 아니다. 하나의 코 루틴이 다른 코 루틴과 다른 콜 루틴간에 양보하면 차단됩니다. 바닐라 루아에는 두 개의 동시 실행 포인터가있을 수 없습니다.

그러나 외부 라이브러리를 사용할 수 있습니다. 가장 인기있는 것 중 하나는 Lua Lanes입니다.

+0

'socket.http'를 더 자주 출력하여 비교하는 것이 더 쉬운 것처럼 보입니다. 그러나 라이브러리 코드를 차단하는 큰 부분을 해결하기 위해서는 큰 해킹이 필요합니다! – Anko