程式名稱: 聊天室之用戶端與伺服端程式

程式規格書

教師:林盈達

 

. 學習目的:

將課堂上所學習之client-server程式撰寫方式及技巧,用於設計一個聊天室,這個server程式可同時支援多個不同主題、且能動態產生或結束的聊天室。

. 背景知識:

如圖一,client-server model主要包括了這四種,針對聊天室同時多人連至server且持續互相傳遞訊息的特性,這四種model中又以concurrent connection-oriented model最為適合聊天室的製作。確認使用TCP作為傳輸協定,並決定以concurrent server來減短對各個client的反應時間後,要製作能同時有多個主題、且能動態產生的聊天室,必須選定更明確的client-server model,這裡我們介紹三種可行的架構,以及這幾種架構基本的程式控制流程。

圖一 四種重要的client-server model

 

single-process concurrent server model的架構如圖二,圖中最左邊的socket負責處理所有連結要求,也就是listen並等待connectaccept之後再交由其他socket負責,在使用者眼中便是login的動作;而其他sockets負責各個connectionserver利用select這個指令,得知各個socket是否有訊息傳入,並作相對應的處理。

 

 

 

這個架構的運作方式很像是在一個大房間,有一個門房負責登記由大門來訪的賓客,登記完之後就開一個窗口給這個賓客,並將探針放在大門及各個窗口,探針上分別牽引著二條代表讀與寫的線連至門房身上,門房不斷察看身上的線,代表大門的線動了就去接待、登記下一個賓客,代表窗口的線動了就去把訊息抓回來處理。

圖二 Single-process, connection-oriented, concurrent server

 

 

 

 

 

 

 

 

 

 

 

需注意的是,這個架構中唯一一個process同時負責好幾間聊天室,因此哪些sockets屬於同一個聊天室、轉送訊息時要傳至哪些clients、各個聊天室為開放或關閉,在程式裡必須用表格清楚記錄相關資訊。

在這個程式中,除了要瞭解一些基本的socket函式,如bindlistenconnectacceptreadwriteclose等的用法外,還會用到select函式,以下便就較特殊的select函式作介紹,其他函式請同學參考課本用法。

Select的用法如下:

Retcode = select ( numfds, refds, wrfds, exfds, time );

Arg Type Meaning


numfds int Number of file descriptors in the set.

refds &fd_set Address of file descriptors for input

wrfds &fd_set Address of file descriptors for output

exfds &fd_set Address of file descriptors for exceptions

time &struct timeval Maximum time to wait or zero

參數中的refdswrfdsexfds就像三組獨立的探針,以refds來說,針對每個input都放一個探針連至窗口,探針上寫著這個窗口的位址,並且將各個input窗口編號,參數所指的第ibit也就是編號idescriptor,可以利用FD_ZERO將每個bit都清除、FD_CLR來清除某個bitFD_SET設定某個bitFD_ISSET檢查某個bit是否已被設定,在聊天室的程式中,由於門房只須探查各窗口是否有訊息要傳遞,因此只會用到refds,所以outputexceptions均設成0,而用作查詢等待答覆上限時間的time參數,在此也可設成0

從架構圖(圖三)中可以發現這個架構除了master process負責接受連結外,

還有數個由master processfork出來的slave processes,每一個slave process負責一個聊天室,且以先前提過的select指令來偵測聊天室內各個sockets的要求。

用這個架構撰寫聊天室,可以簡化表格的設計,由各個slave process各自維持一個使用者資料表格,用於訊息傳遞時的查詢;較複雜的地方則是針對每個連結上來的使用者,若有開新聊天室的需求,必須由master process動態產生slave process,並於聊天室所有使用者均離開時將負責的slave process清除。

圖三 Master & Slave Concurrent Servers

 

 

 

 

 

 

 

 

 

 

 

 

當使用人數龐大時,為了加快開新聊天室的速度,在一些BBS系統上出現

了事先fork出一些slave processes放在pool中,開新聊天室時直接讓先前fork好的slave process去負責,關閉聊天室時再將之放回pool中,架構如圖四所示,這個架構的寫法大致與一般Master & Slave Concurrent Server相同,無庸贅述。

圖四 Pre-allocated Master & Slave Concurrent Servers

屬於同一個processthreads共用相同記憶體的特質,解決了fork 動作中必須複製記憶體內容和所有descriptors,以及在fork完之後,parent process child process必須靠interprocess communication來傳遞資訊的問題。因此,圖三之中的slave process可以用threads取代,大幅減短原本用以產生child process的時間。

threads取代child process來製作聊天室時有兩點需要注意的:

  1. 由於屬於同一個process的不同threads可以共用變數和descriptors,所以會有data synchronization的問題,必須在thread取用共用變數前用mutex變數鎖住此公用變數,以避免超過一個thread同時存取之; 此時,可能會有thread需要等待某些公用變數被unlock,可用condition變數來達到此效果。
  2. 在一般master & slave processes裡使用的函式在threads應用程式中不一定為thread-safe,可能發生在同一台機器上執行clientserver時運作正常,但是由其他台機器連上來的client則無法正常傳送資料的現象,可以用thread-specific data的技巧來解決這個問題。

 

. 功能與輸入輸出:

使用者連上server後,必須提供以下功能:

1.查詢現有聊天室及其主題、各聊天室成員

2.加入原有聊天室,或者開新的聊天室並決定其為開放式或封閉式,當使用者欲加入封閉式聊天室時,系統需送訊息給首開此聊天室的室長,由室長決定是否允許新成員加入。

3.可執行指令包括:

/Room => 列出目前所有聊天室及其主題

/Command => 秀出所有能夠執行的指令及其用法

/Member => 列出目前所有聊天室及其成員

/Join + Room_Id => 加入指定聊天室

/Create + ‘-o’ / ‘-c’ + Topic => 開新的聊天室,並指定聊天室性質為開放或封

閉以及聊天主題

在使用者正式進入聊天室之後,必須能執行以下的基本指令:

Help => 秀出聊天室內所有能夠執行的指令及其用法

Who => 列出聊天室裡的所有使用者及其上線位址,並標示出使用者本身

Nick => 讓使用者換代號

Yell => 將使用者說的訊息告知所有使用者

Tell => 將使用者說的訊息告知指定的使用者

Bye => 離開聊天室

其中封閉式聊天室的室長另外可執行兩個指令:

Admit + Nick => server詢問是否允許讓使用者加入,室長同意其加入時

Reject + Nick => server詢問是否允許讓使用者加入,室長拒絕其加入時

另外可自行選擇加入一般聊天室裡提供的其他功能,舉例如下:

  1. 利用顏色區分自己說的訊息和其他人說的訊息
  2. Color => 將自己對大家說的話、別人偷偷對自己說的秘密及公諸於世的訊

    息以顏色區分

  3. 不再接收來自指定使用者的訊息
  4. Ignore + Nick => 將指定使用者打入冷宮,不再接收來自此人的訊息

  5. 動作,主要分成三大類
  6. Verb + message => //sing 天天天藍

    Verb => //cough

    V + Nick => //kick piggy

  7. 記錄使用者聊天時間、參與的聊天室主題
  8. 查詢聊天記錄

使用者執行client程式連上server以後,須有login的動作,server傳送歡迎訊息給使用者,其中內容除表示歡迎使用聊天室外,還須有聊天室指令介紹,使用者正式進入聊天室之後,附上prompt供使用者輸入指令,整體運作情形舉例如下:

csh > ClientTelnet ChatServer.nctu.edu.tw 5000

login: Venus

歡迎光臨Chat Room Server

本茶館提供以下指令供您差遣

/Room => 列出目前所有聊天室及其主題

/Command => 秀出所有能夠執行的指令及其用法

/Member => 列出目前所有聊天室及其成員

/Join + Room_Id => 加入指定聊天室

/Create + Topic => 開新的聊天室,並指定聊天室主題

進入聊天室後可供差遣項目如下:

/Who => 列出聊天室裡的所有使用者及其上線位址

/Nick => 讓客倌您換個響亮的代號

/Yell => 將您說的訊息公諸於世

/Tell => 幫您稍個訊給指定的使用者

/Bye => 離開聊天室

//Verb + message => 包含singmurmurcomplain

//Verb => 包含coughsleep

//Verb + Nick => 包含kickkissslap

請慢慢享用您的大好時光!

>/Room

1 程式寫作 closed

2 電影討論 open

3 無題閒聊 open

>/Join 1

室長Mars 歡迎您的加入!

> /who

0 Mars 140.113.123.1 <-有光環的室長

1 Vinus 140.113.123.2 <-客倌您各個兒呀!

2 Jupitor 140.113.123.3

3 Saturn 140.113.123.4

>//complain 程式好難寫喔!

<< Vinus 抱怨道『程式好難寫喔!』 >>

Mars:對呀!

<< Jupitor 打起磕睡 >>

Saturn:我要去吃飯飯了,再見!

>再見!

Vinus : 再見!

Mars:再見!

Saturn結帳離開茶館了

 

. 測試步驟:

  1. UNIX環境下執行server程式
  2. client程式連線至server,看到歡迎訊息後,執行CommandRoomCreate,並將聊天室設為open,進入聊天室後,執行WhoNick
  3. 另以兩個clients連上server,加入同一聊天室,假設三個clients分別依進入聊天室的順序為ABCC執行NickWhoYellTell A及其他optional指令
  4. 重複步驟13,將聊天室設為closedA並分別accept Breject CC再度請求進入聊天室,A accept C
  1. 延續單一功能open版測試,由B執行ByeC執行WhoTell BTell A
  2. 延續單一功能open版測試,由A執行ByeC執行WhoTell BTell ABC分別執行ByeD連線至server,執行Room,觀察server是否已經聊天室關閉
  3. 延續單一功能closed版測試,由B執行ByeC執行WhoTell BTell A
  4. 延續單一功能closed版測試,由A執行ByeC執行WhoTell BTell A,另由D連線至server,並要求進入聊天室,觀察server是否自動轉移室長職權至BC
  1. client A開聊天室X,並設為open
  2. client B另開一個聊天室Y,並設為closed
  3. client C執行RoomJoin X,進入聊天室後執行NickWhoYellTell A及其他optional指令
  4. client D執行RoomMemberJoin YB accept D
  5. client E執行RoomMemberJoin YB reject EE create 聊天室Z,將聊天室設為open
  1. 延續多個聊天室功能測試,B執行Bye,另以client F連線並要求進入聊
  2. 天室Y,觀察室長職權是否正確轉移至DD accept F

  3. E執行Bye,另以client G連線並執行Room,觀察聊天室Z是否已關閉

. 問題討論:

  1. 背景知識中提供的四種方法分別有何優缺點?各適用於哪些情況?
  2. 背景知識中提供的Master & Slave Concurrent Server架構和一般所提的Concurrent Connection-oriented Server架構有何不同?為何在寫聊天室程式時需做這樣的調整?
  3. 除了背景知識中所提到的四種方法可以用來製作聊天室外,還有哪些client-server model可以達到同樣效果呢?在製作上有何差別?
  4. 如果系統提供了可供執行的程式,如edit.exedate.exe等,有哪些函式可以讓server程式呼叫,以執行這些執行檔呢?
  5. 在大多數的socket程式中,都會用到fork指令,由parent process 產生一個child process,這兩個process有何異同?
  6. 其他同學自己想到的問題與討論。

. 報告格式:

  1. 程式名稱、作者
  2. 功能及輸入輸出
  3. 系統設計
  4. 模組設計
  5. 程式功能展示 screen dump
  6. 問題討論
  7. 參考資料

附錄:程式列表 (含註解)

. 參考資料:

  1. W. Richard Stevens, “Unix Network Programming”,2nd edition, Prentice-Hall , 1998.
  2. Douglas E. Comer , David L. Stevens, “Internetworking with TCP/IP “ Volume III , Prentice-Hall , 1996.