2008年6月5日

如何用REBOL寫TCP/IP的Client程式


我還記得約14年前讀大學時寫過的第一個網路程式WinBrick(Windows 3.1的網路對打俄羅斯方塊Tetris),當時使用WinSock API。後來讀研究所時用Java Networking API寫VOD(Video-On-Demand)系統,Java的API比C的WinSock稍微簡單一些,但程式還是不好寫。REBOL的TCP/IP程式設計方式,比起上述兩者,都更簡單。你可以閱讀Carl的這篇部落格文章
經過自己手動實驗之後,我簡單地整理一下重點:
  1. DECODE-URL用來將URL(例如:http://www.rebol.com/index.htm)拆解成區塊(例如[scheme: 'http host: "www.rebol.com" port-id: 80 path: "/index.htm"]),但是DECODE-URL有時候會拆解錯誤,如果與到拆解錯誤的狀況,就必須自己處理。如這個例子所示。
  2. 上述的區塊可以當作OPEN的參數,就可以連接到伺服器。
  3. 如果host是host-name,則程式會先連到DNS,查詢(lookup)伺服器的ip,所以會收到「lookup」事件,這個時候,必須再次呼叫OPEN。
  4. 如果host本來就是host-ip,則不會有上述的步驟(不會收到lookup事件)。
  5. 當程式收到「connect」事件時,表示程式對伺服器的連線請求,已經被伺服器接受(accept),可以開始進行資料通訊,這個時候,通常是由Client先傳送資料(服務請求)給伺服器,而伺服器先聆聽(listen)。因此,在收到connect事件時,Client通常會呼叫WRITE。
  6. 當資料寫入完畢,Client會收到「wrote」事件。這個時候,通常會呼叫READ,進行資料的讀取。當然,你也可以會直接呼叫CLOSE,主動關閉網路連線,這由你的通訊協定(protocol)決定。
  7. 呼叫READ,就會從緩衝區(buffer)讀取資料,一旦讀取完目前緩衝區的資料,就會收到read事件(這個read是「過去分詞」,表示「已經讀取了」)。
  8. 通常你需要解析剛剛讀到的資料,以瞭解資料是否已經讀完。如果尚未讀完,你必須繼續呼叫READ來繼續讀取資料。如果已經讀完,你可能會呼叫WRITE傳資料給伺服器,或者呼叫CLOSE來關閉連線。
  9. 當連線的兩端中,任何一端先呼叫CLOSE來關閉連線時,Client都會收到「close」事件。當client收到這個事件的時候,要做一些收尾的動作。
  10. awake的傳出值如果為false,表示port尚未處理完畢;如果為true,表示port處理完畢,會立刻結束這個port。通常我們會在遇到通訊協定格式錯誤、事件無法識別、或收到close事件之後,傳出true,其他狀況則傳出false。
  11. 為了避免任何動作做太久,我們通常會在外部呼叫WAIT,等候一段Timeout的時間。

沒有留言: