2014-01-08 44 views
0

我有一個PHP腳本(我使用Laravel開發)將用於下載存儲在webroot之外的文件。 我現在想要控制正在進行的下載的傳輸速度(例如,根據傳遞到正在運行的腳本的某個值,在while(fread())調用中執行usleep(),以便可以在外部更改傳輸速度實時),但我無法將值傳遞給正在運行的php腳本。如何將值傳遞給正在運行的腳本?

while($buffer = fread($fp, 2048)) { 
    print $buffer; 
    flush(); 
    $this->bytes_transferred += strlen($buffer); 
      usleep($this->transfer_delay); 
} 

因此,這裏是我的問題: - 我怎麼傳遞,可以在一段時間()週期內被截獲的值?

我能想到的一些理論的解決方案,但他們都有問題:

理論解#1 - 使控制器類有一個類全局變量(如$這個 - > transfer_delay)來控制速度

  • 註冊事件偵聽器,將,不知何故,改變全局變量的值,然後while循環可以簡單的叫usleep($這個 - > transfer_delay)

理論解決方案#1問題 - 我試過使用事件,但我的事件似乎沒有運行。

此外,我懷疑事件運行在不同的上下文中,而不是在實例化的方法/類中運行。

理論解決方案#2 - 打開套接字並收聽活動!

  • 在進入while循環之前,請打開套接字並偵聽事件!

問題理論解#2 - 插座要求您阻塞等待新的連接,所以在等待一個新的方面,我將無法傳送文件

  • 也許我fork()可以處理接受新連接並處理它們的部分代碼?但後來我無法將價值回傳給父母,對吧? (或者我可以使用某種信號處理程序嗎?)

理論解#3 - 從DB每次我通過我的週期循環時間

  • 有外部進程的值推到一個數據庫,並具備同時拉事件()循環讀取從每次迭代

問題理論解#3數據庫 - 它讓我覺得髒內:O)

  • 我不認爲這是很好的做法,多次打一個數據庫每秒鐘在「高速而()循環」得到一個值

理論解#4 - 使用命名管道

  • 創建一個fifo文件並在每次迭代時從中讀取。

問題理論解#4 - 這其實在我看來是最好的解決辦法:○\

  • 老實說,我想不出有什麼優於這一點,但...必有做我能做的事嗎?

有關如何完成我想要做的事情的任何想法?

+0

只要您在每次讀取後關閉文件,就可以讓PHP從文本文件讀取速度,然後在腳本運行時更改速度。 –

+0

使用第三種理論,但使用內存中緩存而不是數據庫。在學術上,這似乎是好的,實際上,這似乎是這個問題的錯誤語言。 – user602525

回答

0

你可能會使用會話,然後讓一個小的PHP腳本改變會話變量的值。您將遇到鎖定問題,您的while循環可能會被更小的PHP腳本中的文件鎖定阻塞,直到較小的PHP腳本釋放其對會話文件的鎖定。您可能會迅速關閉並開啓會議,以防止任何類似的鎖定顯着減慢轉移速度。

(這會阻止您從一個會話同時上傳多個文件,但通常不是問題)。

+0

我還沒有弄糟一段時間的會話,但我不完全明白我會如何使用它們的東西呢? 在我的情況下,兩個不同的進程將控制下載: a)用戶下載文件,以便PHP腳本將繼續運行,直到下載完成 b)外部進程獲取更改正在進行的傳輸速度的請求轉移,並以某種方式與正在運行的PHP腳本進行通信,併爲其提供一條新的指令,以便遵循 – user3158527

+0

您能否告訴我一個如何註冊會話變量並使其可以被完全外部進程訪問的示例? (例如,會話不是由發起下載的同一用戶共享的) – user3158527

+0

哦,我不知道該速率正在由用戶未啓動的腳本進行調整。在這種情況下,你可能會在數據庫(甚至是文本文件)中記錄會話ID,並讓腳本通過查找id打開會話,並使用該會話的'session_id($ ID)'開始一個會話。這非常類似於一個命名管道,基本上你有一個文件和一個名稱/ ID並寫入它以進行通信(我最初公佈答案時沒有看到該解決方案)。 –

0

我使用memcached解決了我的問題。 我不知道這個解決方案有多棒(因爲我覺得每次發送一個緩衝區或者做一個if條件都會浪費資源從memcached讀取數據,所以我只會每隔X秒檢查一次memcached的速度限制或發送()s)但是...它的工作原理!

相關問題