天天看點

推技術聊天室的實作(下)

下面我們來看看具體實作流程:

  聊天伺服器的實作

  我們的伺服器的核心部分是ThreadedChatHandle類,我們需要處理的資料主要包括兩部分——線上清單和使用者發言。線上清單可以直接使用大的對象數組,這是基于一個聊天室容量是有限制的考慮。而使用者的發言直接發到管道裡面就可以了。

  線上清單類的定義如下:

  class Chater

  { private static Double id;//這個ID作為差別号,同時

   private Double socketid; file://與聊天主幀對應的Socket相關聯。

   private String nickname;// 使用者昵稱

   private String passwd;// 使用者昵稱

   private Int privilige;//

   private String[] filter;//某個使用者的過濾清單

   private Double login_time;//記錄登入時間,用以清除一些逾時聯接

   private String color;//使用者聊天顔色

  ……//限于篇幅,省略了相關的方法。

  }

  注意:以上使用者資料大部分是在login階段,使用者通過身份驗證以後填入的。隻有socketid要等到聊天主幀(一個普通的聊天界面包括聊天主幀,發言幀,線上清單幀三個部分)顯示以後才得到。如果超過一定時間,socketid還是沒有填入,說明浏覽器取得主架構以後連接配接中斷了,這時候就需要删除該使用者資料。如果要實作象sohu那樣的私聊的話,還應該增加使用者IP位址的屬性。

  使用者發言類的定義如下:

  class Content

  { private Double timestamp;//時間戳

  private Double fromChaterid;//發言人id

  private Double toChaterid;//聊天對象id

  private Boolen isSecurity;//是否私聊标志

  private String theContent;//聊天内容,在建構器裡處理過,已經包括表情等ht

ml文本。

  ……//限于篇幅,省略了相關的方法。

  }

  

  核心的ThreadedChatHandle類主要處理的工作是分析使用者請求。用戶端發送的請求的值,主要有login(驗證身份,顯示聊天室主架構)、joinchat(初始化聊天資訊,如顯示歡迎等,顯示聊天内容顯示幀,并保持連接配接,發送聊天資訊。)、showtalk(顯示發言的幀)、names(顯示線上清單幀)、leave(使用者點選按鈕離開聊天室)等等。

假如我們使用GET方法傳遞資料而不是通過POST方法送出表單的話,使用者資料輸入都是在URL裡傳送,下面是幾個url執行個體,結合後面用戶端流程,可以更好地了解ThreadedChatHandle類的職能:

  這是一個使用者名密碼均為’aaa’的聊天使用者登入系統,說了一句話“hello”,然後退出所産生的一系列請求:

  /login?name=aaa&passwd=aaa

  /joinchat?chaterid=555

  /showtalk?chaterid=555

  /names?chaterid=555

  /speak?chaterid=555

  /leave?chaterid=555

  ……

  以上是伺服器程式流程,實際上我們參數的傳遞不能隻傳一個 chaterid,還需要有個對應的認證。而names傳遞一個chaterid是為了更新時間線上清單類内自己通路的時間,避免連接配接逾時。下面我們從用戶端看看具體登入過程。

  聊天界面由三個frame組成,其中joinchat幀是聊天内容顯示部分;showtalk幀是使用者輸入部分,包括聊天内容輸入、動作、過濾以及管理功能都在這一幀輸入;names是線上名單顯示部分,這一部分是定時重新整理的。

  讓我們從浏覽器的角度來看看進入聊天室的過程。

  ◆首先浏覽器請求頁面

  http://host:8080/login?name=NAME&passwd=PWD

  此時一個ThreadedChatHandle出現(包括了一個socket連接配接),并發送了一行資料:

  GET /login?name=NAME&passwd=PWD HTTP/1.1

  ◆伺服器生成一個session id,驗證密碼以後,發回:

  HTTP/1.1 200 OK

  <其他頭資訊>

  Content-TYPE: text/html

  <空行>

  <html>

  ……

  <frameset cols="*,170" rows="*" framespacing="1">

   <frameset rows="*,100,0" cols="*" framespacing="0">

    <frame src="/joinchat?chaterid=555" name="u" frame noresize>

    <frame src="/showtalk?chaterid=555" name="d" frame noresize>

   </frameset>

   <frame src="/names?chaterid=555" name="r" noresize>

  </frameset>

  ……

  </html>

  然後ThreadedChatHandle.start()退出,本子線程結束

  ◆浏覽器收到以上html檔案後,将會依次打開三個聯接(其中的chaterid是需要傳遞的變量,555是個虛指):

  /joinchat?chaterid=555

  /showtalk?chaterid=555

  /names?chaterid=555

  這三個聯接中的第一個聯接joinchat在整個聊天過程中都是保持聯接的,這樣從浏覽器角度來看,就是一個始終下載下傳不完的大頁面,顯示效果上就是聊天内容不是靠重新整理來更新,而是不斷地向上滾動。通過察看html代碼可以看到,隻有<html><body>,然後就是不斷增加的聊天内容,沒有</body></html>。

  另外兩個聯接在頁面發送完畢以後,處理這兩個連接配接的線程就結束了。

  這樣一次登入聊天室實際上有四個子線程響應,但登入完成以後,隻有處理joinchat幀的線程依然存活,用于接收來自伺服器的聊天資訊,這是基于推技術聊天室的關鍵所在。

  當然,如果使用者有其它操作的請求,例如使用者注冊、修改昵稱、修改密碼等操作都可以通過類的擴充得到相對應的響應。通過對類方法的重載還可以比較友善的根據需要修改使用者認證機制與網站其它功能子產品結合在一塊。

繼續閱讀