• 沒有找到結果。

四. 系統設計與實作

4.3. 網路連線功能

本節將分為三個部分,一個部分為單純的 HTTP 協定連線與下載功能的實現,另一 個部分為檔案下載的排程器,第三個部分則是與多媒體講解呈現播放器的整合。

4.3.1. HTTP 協定連線與下載功能

本功能利用 Berkeley Socket 的 API 來設計與實作。運作流程如圖21:

圖 21:利用 HTTP 協定下載檔案流程 接下來解釋上述流程與實作方法。

34

(a) 設定 URL:設定欲下載的檔案的 URL,如:

http://pcmanx.csie.net/release/pcmanx-gtk2-0.3.5-1_FC6.i386.rpm (b) 利用 URL Parser 將(a)中的 URL 解析成三個部分:protocol、host、object,

如上例的 URL 可以解析如下:

(d) 連線成功後,接著產生 Request Header。Request Header 為一組字串,內容 記載與 Http Server 溝通與要求檔案的資訊,圖22為一要求下載(a)中所指 的檔案的 header 範例:

圖 22:Http Request Header Example

Header 裡也可以指定"Range: bytes=a-b",其意義檔案要求下載的範圍為從第 a byte 到 byte,這也是我們實現檔案下載續傳的實作方法。

35

(e) 送出 Header 後,Http Server 也會回傳一個 Header ,來通知要求的結果,

如果檔案存在,且允許下載的話,在 Header 之後,會接著將檔案的內容傳送過 來。

圖 23:Http Server 回傳的 Header 與資料

我們可以從 Http Server 回傳的 header 裡的資料來判斷要求的結果,圖23 中的 server status 後面接的數字即是連線的結果,連線的結果大概可以分成 三類:

 Server status<200 且 Server status>=400 通常是連線錯誤。

 Server status>199 且 Server status<300 表示連線成功。

 Server status>299 且 Server status<400 表示檔案不在此伺服器中,並 會在 Header 裡附上這個檔案的真實位址。

Content-Length 則是我們要求的檔案的大小。

(f) 開始下載檔案,下載完成後,結束此流程。

4.3.2. 檔案下載排程器

檔案下載排程器是以 4.3.1 節為基礎再做延伸與改進。運作流程如圖24:

36

圖 24:檔案下載排程器運作流程圖 接下來解釋流程與實作方法:

(a) 開始下載前,先將需要下載的檔案建立表格來儲存,表格如表8所示,欄位名 稱與意義如下:

 File Name :檔案名稱。

 URL Location:欲下載的檔案的位址。

 File Size:檔案的大小。

 Un-Completed Size:檔案尚未下載完成的大小。

 Status:該檔案目前的狀態:

DM_IDLE:閒置且尚未下載完成。

DM_COMPLETE:下載完成。

DM_ERROR:下載失敗。

表 8:檔案下載列表 表 9:Domain Name 與 IP 對照表

37

填表時,File Size 與 Un-Completed Size 預設為-1,Status 預設為 DM_IDLE。

(b) 解析表8中的 URL,取得 Host Domain Name,並利用 Berkeley Socket 提供 的 gethostbyname_r() 函數來取得 Host IP。由於 Domain Name 需透過查詢 Domain Name Service Server 上的對照表才能取得真實的 IP ,有了真實的 IP 才能做連線動作。加上大部分的多媒體講解呈現檔案都放置在同一個主機,所 以我們設計的方式是將查詢到的 IP 建表,放入表9的表格中,這樣做的好處 有:

 不用重覆查詢真實 IP。

 避免 thread 被 block 住:gethostbyname_r()是阻塞式的,程式會被暫 停直到查詢完成為止。

 減少連線時間的浪費:查詢真實 IP 的動作,需要連線到 Domain Name Service Server,每次查詢,都要花費一段時間。

(c) 初始資料完成後,接下來產生一個 thread 來執行下載的動作,動作如下:

 利用一個迴圈檢查檔案列表的狀態,若狀態為 DM_IDLE ,設定下載範圍(需 要繼傳時)後,開始執行下載動作。

 若狀態為 DM_ERROR,則將狀態設成 DM_IDLE,再執行連線下載。這樣做的 目的是為了避免偶發的連線錯誤。

38

圖 25:整合下載功能的多媒體講解呈現播放器流程圖 整合步驟如下:

(a) 修改主程式 main,使之可以接受參數:

int main() => int main( int argc , char** argv )

利用判斷參數字串的存在與否,來決定是否從網路下載教材檔案。

 參數為空字串:

代表需使用者由檔案系統中選取要播放的多媒體講解呈現檔案。

 參數不為空字串:

參數字串為 http://xxx.xxx.xxx/xxx/publish.xml,利用 4.3.1.實作的模 組下載該檔案來解析其它需下載的檔案。若參數字串為非有效的網址,則 會因無法下載而中止程式。

(b) 解析步驟(a)下載的 publish.xml 取出課程所需的檔案來建出 4.3.2.所指的列 表後,利用 4.3.2.實作的模組開始下載檔案列表裡的檔案。

(c) 由於使用 thread 的關係,步驟(b)在執行的同時,主程式會並行往下執行,所 以我們需要在原本開檔的地方前面,利用 timer,每一段時間檢查要播放的檔 案是否被下載完成,等檔案下載完後才接著開檔動作。在這裡,我們是檢查(b) 建立的列表裡的 Status 欄位來確認下載狀態。當檔案下載完成後,Status 會 變成 DM_COMPLETE,在 timer 裡檢查 Status 為 DM_COMPLETE 後,才會接著執行 開檔以及之後的功能。

(d) 當使用者從多媒體講解呈現播放器畫面上的課程檔案列表(如圖26)指定要播

39

放的檔案時,若此時存在下載檔案的 thread ,則程式會先中斷 thread 的執 行,並等待 thread 被結束,再以指定的檔案為檢查的起點,重新執行(b)步驟。

圖 26:課程檔案列表

在 thread 被通知結束到主程式等待 thread 真正結束之間,若使用者再透過畫 面上的課程檔案列表指定要播放別的檔案時,則會產生死結,造成程式被鎖死。

在此我們修改 UI 的事件處理,在通知 thread 需終止時,先將點選列表時會傳 送的訊號(這個訊號會呼叫執行步驟(b)的函式)鎖住,等主程式確定 thread 終 止完成後,再恢復該訊號的傳送。

相關文件