2015年10月22日 星期四

Indy - TCP 之一 - 以 TIdTCPServer 自製檔案伺服器 (1)

緣起

自 2001年9月, 我的第四本書- Delphi/Kylix Indy 網際網路程式設計出版之後,忙工作,忙教學,不知不覺也過了十幾年。 (好可怕啊~~~ 時光艿苒就是這種感覺嗎?)

在這期間我也曾經發過幾次神經,想要把該書改版一下,當時撰寫的時候,那時空背景是 Delphi 7, Kylix 3, Indy 8.0.25 轉 Indy 9 的時候,現在 Delphi XE7 都舉行了預覽發表會,Kylix 已經緲緲不知所蹤,Indy 都到 10.5 以後的版本了。

但曾和幾家台灣地區較為知名的出版社接洽出版,得到的回音不外乎:『目前還有人在寫 Delphi 喔?』『現在出寫程式的書沒有人要買了,如果你寫 PhotoShop 怎麼修照片的書,我們就出』,而我對於 PhotoShop 的使用,只停留在剪貼、放大縮小、模糊、去背的基本使用,所以還是不獻醜了。

從 2001年到現在2014年,13個年頭過去了,對於Indy相關的應用不少,但真正用到Indy強大功能的不多。這幾年從沒間斷在程式寫作上的浸淫,Delphi 除了 2009-2011之間,我把重心稍微轉到 Objective-C 的階段之外,也從來沒放下過,但看到對Indy真的運用的很棒,居然只有 Embarcadero.

別說 Embarcadero 是原廠,所以他們就自然會對Indy 熟悉,這是牽強的說法,因為Indy從 WinShoes 開始,都是OpenSource 的軟體元件,只要你肯花點時間,一定能很快熟悉它,甚至寫些元件發佈給 Indy 用,君不見,TIdDNSServer 就是筆者所寫?

扯遠了,拉回來。

Embarcadero 這幾年在 Delphi XE3 之後新增的 Server 端元件,不僅是傳統的 DataSnap server 支援了 TCP/IP與 REST 兩種模式,用的就是 Indy 元件來寫的,大家可以花點時間進去 C:\Program Files (x86)\Embarcadero\Studio\14.0\source 這個目錄看看, 裡頭真的花了很多心思,用 Indy 用的非常精闢。

舜何人? 予何人? 有為者亦若是!

筆者可能算是比較老派的,所以老愛掉書包,我們也別落人後,今天就來個範例,讓大家寫寫 Indy 小程式,做做傳遞檔案的功能吧。

可能您會說:我用 FTP Server 就好了,我用 Apache 加 PHP 用 Upload File 來做就好了等等。

我的回應是:都很好,能達成功能,不傷身體就好,但多學一種方法也不錯,最近不是有個廣告,比別人多會一招,勝算就多一成?

就來多學這一招半式吧。

使用時機

什麼時候會用到這東西? Indy 會飛嗎?

別再亂鬧了,哪天你的專案需要傳檔案,你就等著哭吧!

如果哪天專案要把資料回傳到 Server, 而這些資料又是檔案,架設 FTP 是OK的,到時候你還是得寫個 FTP Client 來上傳, 而且設定也還是得花時間寫的。

不多說,來看一個簡單的 TCP Server 是怎麼運作的吧,FTP Server 跟 HTTP Server 都不例外喔。

TCP Server 的運作,就是從啟動開始,先建立一些等待的 Queue, 也就是上圖裡面的等待隊序,像 TIdTCPServer 預設的 ListenQueue 數量就是 15 個, 當然可以隨我們的需要來修改這個數字。

在等待的過程當中,一旦有使用者連線進來了,就會由其中一個線程來處理這個使用者的需求,等這個使用者的需求處理完畢,該連線就會由 Client 或 Server 端來切斷。

命令有哪些?

這個問題很好,既然現在我們正在製作一個新的 Server, 也就沒有傳統命令的包袱,我們可以自己來決定,以下我們假設要讓特定的 Client 端傳送檔案到 Server 來,所以可以來定義幾個簡單的命令,你也可以把這些個命令當成通訊協定,因為本來這就是一個自定的通訊協定。

我們定義有以下幾個簡單的命令:
filename
filereplace
fileresume
sendfile

命令的順序要正確,不然就從 server 端強制斷線,我們定義順序如下:
Client                                                          Server
 "sendfile Open-Sesume" -------------------->

             <----------------------------- "200, OK, Please send file name, size, data"

"filename 要存放在 server 端的檔案路徑"--->

             <----------------------------- "200, ok, ready for get file: 檔案路徑"

"filesize 檔案大小" ------------------------------>

"檔案內容" ---------------------------------------->

             <----------------------------- "200, ok, file accepted"

Server 端只存放 filesize 後面所帶的數字描述的資料量,多的全放棄,接著,Server 斷線。

講到這裡,概念說完了,就是 Client 跟 Server 之間把字串送來送去,如此而已,接著,我們要來看怎麼用 Indy 達成這個要求了,請接著看Part2.

沒有留言:

張貼留言