• 沒有找到結果。

第四章 Client 端和 Server 端實作

4.3 Rdesktop Media Server

4.3.2 Web Server

我們利用 BCB6 內建的 Indy 的 IdHTTPServer 元件完成 Web Server。圖 4-18 為 IdHTTPServer 元件的圖示。

圖4-18. IdHTTPServer 元件

將屬性中的Port 設定為 667,這個 Port 就是 Web Server 對外的處理窗口。利用事件 中的 OnConnect 和 OnDisconnect 判斷是否有 Client 連線進來。最重要的事件是 OnCommandGet,當 Client 有個 GET 的請求訊息,會觸動這個事件連結的函式。這個函

式處理請求檔案的資料傳送,包含中斷點下載。中斷點下載的功能,決定了MPlayer 是

否可以對檔案進行搜索,也就是快轉和倒轉的功能。

RFC2616 定義 HTTP 1.1 的請求訊息有八種方法:OPTIONS、GET、HEAD、POST、

PUT、DELTETE、TRACE 和 CONNECT。常用的四種方法為 GET、POST、PUT 和 DELTETE。[13]

1. OPTIONS:和 Client 說明網頁資源的需求和選項。

2. GET:從 Server 取得資源。

3. HEAD:和 GET 相同,只是 Server 僅回傳標頭資訊而不回傳網頁資源。

4. POST:在 Server 上建立網頁資源。

5. PUT:更新 Server 上的網頁資源。

6. DELTETE:刪除 Server 上的網頁資源。

7. TRACE:將 Client 的請求從 Server 回傳給 Client。

8. CONNECT:保留給 proxy 使用。

IdHTTPServer 元件包含 OnCommandGet 和 OnCommandOther 的請求事件,處理 GET 方法為OnCommandGet 事件,其他方法則用 OnCommandOther 事件。

1. OnCommandGet 事件

OnCommandGet 事件為 Client 發出 GET 的 HTTP 請求訊息時所觸發的事件。圖 4-19 為OnCommandGet 事件流程,首先判斷請求檔案是否為“/Video”。如果否就回傳 404 代

碼,表示檔案不存在。是的話,檢查是否有請求中斷點下載,有的話回傳206 訊息,並

僅傳送該範圍的檔案資料。沒有請求中斷點下載,則回傳200 訊息,並傳送整個檔案。

圖4-19. OnCommandGet 事件流程

2. 請求訊息

圖4-20 為 MPlayer 請求檔案的標頭訊息;圖 4-21 為請求部份檔案的標頭訊息,兩 者差別在於部份檔案多了“Range: bytes=10240-”。 “Range: bytes=10240-”的意思為請求 Web Server 從檔案的第 10240 位元組開始傳送。注意的是檔案的最開頭位置是從第 0 個 bytes 開始算。

GET /Video HTTP/1.0 Host: 140.113.13.81:667

User-Agent: MPlayer/1.0rc2-4.1.2 Icy-MetaData: 1

Connection: close

圖4-20. MPlayer 請求檔案

GET /Video HTTP/1.0 Host: 140.113.13.81:667

User-Agent: MPlayer/1.0rc2-4.1.2 Icy-MetaData: 1

Range: bytes=10240- Connection: close

圖4-21. MPlayer 請求部份檔案

BCB6 中內建的 Indy IdHTTPServer 元件,沒有解析檔案範圍的功能,所以要自行用 字串比對的方式將檔案範圍的請求找出來。然後在傳送檔案的時候,要將檔案讀取位置 跳到檔案請求的起始位置。

3. 回應訊息

回 應 的 標 頭 訊 息 中 , 對 於 MPlayer 來 說 最 重 要 的 參 數 為 Response No. 、 Accept-Ranges、Content-Type 傳送 Content-Length 和 Content-Range。圖 4-22 為回應 200 代碼的標頭訊息;圖4-23 為回應 206 代碼的標頭訊息;圖 4-24 為回應 404 代碼的標頭 訊息。

HTTP/1.1 200 OK Accept-Ranges: bytes

Server: Rdesktop Media Server

Content-Type: application/octet-stream Content-Length: 44176206

圖4-22. Web Server 200 回覆訊息

圖 4-22 為回應 200 代碼的標頭訊息。Accept-Ranges 決定中斷點下載與否;

Content-Type 為 檔 案 的 MIME 型 態 , 這 邊 都 是 回 應 “application/octet-stream” 。 Content-Length 為傳送的檔案大小。

HTTP/1.1 206 Partial Content

Content-Range: bytes 12582912-44176205/44176206 Accept-Ranges: bytes

Server: Rdesktop Media Server

Content-Type: application/octet-stream Content-Length: 31593294

圖4-23. Web Server 206 回覆訊息

圖4-23 為回應 206 代碼的標頭訊息。當接收中斷下載的請求,回應代碼要改為 206,

並 且 利 用 Content-Range 的 欄 位 說 明 檔 案 的 範 圍 。 Content-Range “bytes 12582912-44176205/44176206” 意 思 為 目 前 要 傳 送 的 檔 案 為 第 12582912 位 元 組 到 44176205 位元組/檔案全部大小為 44176206 位元組。此時回應 Content-Length 的值為該 部分檔案的大小。

HTTP/1.1 404

Server: Rdesktop Media Server Content-Type: text/html

圖4-24. Web Server 404 回覆訊息

圖 4-24 為回應 404 代碼的標頭訊息。這是代表請求的檔案不存在,所以也不會有

任何檔案描述的訊息。

4. 檔案傳送

不論是傳送完整檔案或部份檔案,都是將檔案切成BLOCKSIZE 的大小傳送。一個

原因是 IdHTTPServer 元件只提供傳送整個檔案的函式,沒有傳送部份檔案的函式。另 一個原因是可以將檔案切成TCP 封包的最大值(MSS)傳送。

從硬碟開啟檔案,更改檔案讀取的位置。宣告一個記憶體空間,從檔案位置讀取 BLOCKSIZE 的資料到記憶體。透過 TCP 將記憶體資料傳送給 Client,傳送完成回到讀 取檔案,再透過TCP 傳送,直到檔案傳送完畢。 圖 4-25 為傳送檔案的流程。

BCB6 程式細節。首先利用 TFileStream 將檔案開啟成唯讀模式,更改檔案讀取的位 置。建立一個TMemoryStream 的資料,利用 CopyFrom()函式從 TFileStream 讀取資料到 TMemoryStream,讀取的大小為 BLOCKSIZE。將 ResponseInfo 結構中的 ContentStream 指定為TMemoryStream 的資料,再利用 WriteContent()指令傳送。使用 ContentStream 傳 送資料,將會把原本傳送的資料釋放掉,所以進行下一個區段傳送要再建立一個 TMemoryStream。如此反覆傳送資料,直到整個檔案傳送結束。

圖4-25. 檔案傳送流程

目 前 可 以 被 Ethernet 接 受 的 MTU(Maxumum Transmission Unit) 最 大 值 為 1500bytes。扣除 IP 標頭 20bytes 和 TCP 標頭 20bytes,最大 TCP 可以傳送的資料(MSS) 為1460bytes。所以 BLOCKSIZE 的值選擇 1460bytes。

傳送速度是利用1 個 Timer 元件,計算 1 秒內總共傳送幾個 BLOCKSIZE 的資料,

再換算成每秒傳輸的位元組數。而傳送進度是用Progress Bar 顯示目前檔案位置的百分 比。