程式名稱
: 聊天室之用戶端與伺服端程式程式規格書
教師:林盈達
一
. 學習目的:將課堂上所學習之client-server程式撰寫方式及技巧,用於設計一個聊天室,這個server程式可同時支援多個不同主題、且能動態產生或結束的聊天室。
二
. 背景知識:圖一
四種重要的client-server model
single-process concurrent server model的架構如圖二,圖中最左邊的socket負責處理所有連結要求,也就是listen並等待connect,accept之後再交由其他socket負責,在使用者眼中便是login的動作;而其他sockets負責各個connection,server利用select這個指令,得知各個socket是否有訊息傳入,並作相對應的處理。
這個架構的運作方式很像是在一個大房間,有一個門房負責登記由大門來訪的賓客,登記完之後就開一個窗口給這個賓客,並將探針放在大門及各個窗口,探針上分別牽引著二條代表讀與寫的線連至門房身上,門房不斷察看身上的線,代表大門的線動了就去接待、登記下一個賓客,代表窗口的線動了就去把訊息抓回來處理。
圖二 Single-process, connection-oriented, concurrent server
需注意的是,這個架構中唯一一個
process同時負責好幾間聊天室,因此哪些sockets屬於同一個聊天室、轉送訊息時要傳至哪些clients、各個聊天室為開放或關閉,在程式裡必須用表格清楚記錄相關資訊。在這個程式中,除了要瞭解一些基本的
socket函式,如bind、listen、connect、accept、read、write、close等的用法外,還會用到select函式,以下便就較特殊的select函式作介紹,其他函式請同學參考課本用法。Select的用法如下:
Retcode = select ( numfds, refds, wrfds, exfds, time );
Arg Type Meaning
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
參數中的
refds、wrfds、exfds就像三組獨立的探針,以refds來說,針對每個input都放一個探針連至窗口,探針上寫著這個窗口的位址,並且將各個input窗口編號,參數所指的第i個bit也就是編號i的descriptor,可以利用FD_ZERO將每個bit都清除、FD_CLR來清除某個bit、FD_SET設定某個bit、FD_ISSET檢查某個bit是否已被設定,在聊天室的程式中,由於門房只須探查各窗口是否有訊息要傳遞,因此只會用到refds,所以output及exceptions均設成0,而用作查詢等待答覆上限時間的time參數,在此也可設成0。從架構圖(圖三)中可以發現這個架構除了
master process負責接受連結外,還有數個由
master process所fork出來的slave processes,每一個slave process負責一個聊天室,且以先前提過的select指令來偵測聊天室內各個sockets的要求。用這個架構撰寫聊天室,可以簡化表格的設計,由各個slave process各自維持一個使用者資料表格,用於訊息傳遞時的查詢;較複雜的地方則是針對每個連結上來的使用者,若有開新聊天室的需求,必須由master process動態產生slave process,並於聊天室所有使用者均離開時將負責的slave process清除。
當使用人數龐大時,為了加快開新聊天室的速度,在一些
BBS系統上出現了事先
fork出一些slave processes放在pool中,開新聊天室時直接讓先前fork好的slave process去負責,關閉聊天室時再將之放回pool中,架構如圖四所示,這個架構的寫法大致與一般Master & Slave Concurrent Server相同,無庸贅述。圖四
Pre-allocated Master & Slave Concurrent Servers屬於同一個
process的threads共用相同記憶體的特質,解決了fork 動作中必須複製記憶體內容和所有descriptors,以及在fork完之後,parent process 和child process必須靠interprocess communication來傳遞資訊的問題。因此,圖三之中的slave process可以用threads取代,大幅減短原本用以產生child process的時間。以
threads取代child process來製作聊天室時有兩點需要注意的:
三
. 功能與輸入輸出:
使用者連上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詢問是否允許讓使用者加入,室長拒絕其加入時
另外可自行選擇加入一般聊天室裡提供的其他功能,舉例如下:
Color => 將自己對大家說的話、別人偷偷對自己說的秘密及公諸於世的訊
息以顏色區分
Ignore + Nick => 將指定使用者打入冷宮,不再接收來自此人的訊息
Verb + message => //sing 天天天藍
Verb => //cough
V + Nick => //kick piggy
使用者執行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 => 包含sing、murmur、complain
//Verb => 包含cough、sleep
//Verb + Nick => 包含kick、kiss、slap
請慢慢享用您的大好時光!
>/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結帳離開茶館了
四
. 測試步驟:天室Y,觀察室長職權是否正確轉移至D,D accept F
五
. 問題討論:六
. 報告格式:附錄:程式列表
(含註解)七
. 參考資料: