6

大きなファイルをダウンロードしながら、他のことも同時に処理したい。

ただし、を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!

ご覧のとおり、dprintRoutineが最初です。resume数字の1とyieldsを出力します。次にdownloadRoutine、はresumedであり、。を生成せずにファイル全体をダウンロードします。そうして初めて、残りの数字が印刷されます。

自分のソケットライブラリを書きたくない!私に何ができる?

編集(同じ日遅く):一部のMUSHユーザーも気づいています。彼らは役立つアイデアを提供します。

4

2 に答える 2

5

PiLアドバイスcopasライブラリを使用できない理由がわかりません(これは、ここで示したものとほぼ同じ答えです)。

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()

次に、addthreadfrom copasを使用して、非ブロッキングソケットを提供し、step/loop関数を使用しreceiveて、受信するものがあるときに実行できます。

copasを使用すると作業が少なくなりますが、settimeout(0)直接使用するとより詳細に制御できます。

于 2012-11-12T22:33:41.683 に答える
2

コルーチンはスレッドではありません。それらは協調的であり、同時ではありません。あるコルーチンが別のコルーチンに降伏すると、ブロックされます。バニラルアでは、2つの同時実行ポインターを持つことはできません。

ただし、そのために外部ライブラリを使用することはできます。最も人気のあるものの1つはLuaLanesです。

于 2012-11-11T22:07:34.130 に答える