[Python]用UI展示一個簡單的即時通系統 - 使用Socket

我們那個很有想法的老闆,最近又想了一個新點子,希望我們的設備,可以讓遠端的2台裝置,互相溝通。一開始我想法是,有困難。以我們現有的設備都是走單機版,且利用網路2層結構來說,是很難的。首先我就不知道遠端那個設備在哪裡,IP,Gateway怎給我,等等。

但是後來我想想,站在軟體角度,如果像是teamviewer那種架構,或是類似line聊天軟體,根本不需要知道對方的IP/Gateway,一樣可以連線溝通啊。而且我們設備上層還是軟體架構,如果用軟體架構實現,再去透過抓包解析後設定到硬體,這樣路就通了。所以想說利用Python來快速實做一下聊天軟體,OK的話再回去C++/C# AP那邊添加功能。

簡單來說,就是有一個中央負責處理轉發的Server,以及連線到Server的許多的Client。Client之間,只需要利用ID來識別,就可以傳送資料。就像是聊天軟體一樣簡單達到需求。

「架構規劃與定義」

流程大概就是幾個client端連線之後,可以看到彼此,進而傳遞訊息,因此我畫出底下的圖代表。Server由上而下有時間的順序。
根據上面的圖,可以看出主要溝通訊息可以分成四類:connect(紅),friends(藍),message(綠),disconnect(黃)。原先想用類似C++ structure方式組包來送訊息,但因為這單純聊天比較簡單,只有幾種型態,我就以純文字方式定義就好。訊息中夾帶多組參數,會以"/"隔開。不用反斜線,因為會有跳脫字元問題。
  • 。connect:Client發連線訊息給Server,夾帶name訊息。Server會建立新連線。
  • connect/name:Client1
  • 。friends:Server接收到connect/disconnect訊息時,會整理朋友列表清單,傳送給所有Client。
  • friends/client1/client2
  • 。message:Client1傳送聊天訊息給Server,Server根據來源目的,轉發給Client2。
  • message/to:Client2/from:Client1/hello
  • 。disconnect:Client發斷線訊息給Server,夾帶name訊息。Server會斷開Client連線。
  • disconnect/name:Client1

「實做部分」

要做到這樣效果,是利用Socket。Python在使用socket上是非常非常方便的。Socket Server/Client的寫法網路上已經一堆了,如何連線,傳送接受,斷線就不用敘述了,底下就說明幾個方向。

Server部分:

      Server需要接收很多連線,故我寫一個簡單class去記錄每一個connection的handle, portnum, 以及名稱,然後把每個connection class去append到一個connection list中,形成一個client列表。我定義Server是被動部分,有連線或是命令進來才有相對應反應,本身不會自己主動發什麼訊息的。因此接收部分,共會接收到三種命令:
    
    
  1. 連線命令:
    • 格式
    • connect/name:client1
    • 處理:分析出client名稱之後,保存至connection list
    • 反應
      1. Server對此client回傳message訊息當做回應,內容為"Hello clientname"
      2. Server根據connection list清單建立friends訊息,回傳給所有connection
  2. 斷線命令:
    • 格式
    • disconnect/name:client1
    • 處理:分析出client名稱之後,從connection list中移除,並關閉連線
    • 反應:Server根據重整後的connection list清單,建立friends訊息,回傳給所有connection
  3. 訊息命令:
    • 格式
    • message/to:client2/from:client1/hello
    • 處理:分析出給那個client名稱,並在connection list清單找到目的client
    • 反應
      1. Server將message訊息轉發給目的client
      2. Server將message訊息轉發給來源client
    
    

Client部分:

    Client部分除了主動向Server傳送訊息之外,還會接收來自於Server的回應。傳送部分有三個命令:
    
    
  1. 連線命令:
    • 格式
    • connect/name:client1
    • 處理:將自己的名稱(ID),組成命令之後,發送至Server
  2. 斷線命令:
    • 格式
    • disconnect/name:client1
    • 處理:用戶按下close之後,將自己的名稱(ID),組成命令之後,發送至Server
  3. 訊息命令:
    • 格式
    • message/to:client2/from:client1/hello
    • 處理:根據用戶選擇的目的client,自己的ID以及要傳送的訊息,組成命令之後,發送至Server
而接收部分也有三個命令:
    
    
  1. 朋友清單命令:
    • 格式
    • friends/client1/client2/......
    • 處理:分析出每個client名稱
    • 反應:添加至朋友清單
  2. 斷線確認命令:
    • 格式
    • disconnect/name:client1
    • 處理:確保Server回應這個client斷線,表示Server已經把client從清單中移除並斷線
    • 反應:關閉視窗
  3. 訊息命令:
    • 格式
    • message/to:client2/from:client1/hello
    • 處理:分析出給來自那個client名稱,以及訊息內容。
    • 反應:顯示在螢幕上

「結果呈現部分」

根據上面定義,實做出畫面。然後覺得server如果是command也太單調,所以也弄了一個界面,就大概長下圖這樣。用界面呈現是因為command視窗不好表現thread,因為畫面被等待輸入lock,但背後有命令進來,輸入畫面會跑掉不好看。

一個Server,以及可以支援多個Client。有多個連線之後,Client可以跟線上其他Client丟訊息,被丟訊息的Client也會看到是誰來的。編碼用utf-8,就可以支援中文:
當我將其中一個連線關閉時,另一個client端也會同步更新清單,可以看見斷線的client被移除了。

「腳本下載」

Server
Client

「後記」

。Server沒有考量到複雜度,所以當client需求多的時候,效率應該會很差。以展示來說應該夠了。
。Server沒有太多功能,重新連線,踢掉Client等功能沒做。界面上只有記錄而已,有單調
。Client因為簡單展示,沒使用帳號密碼登入。
。結構可以再定義更多,比方說分組。
。雖然腳本開始有判斷Python2/3,但實際上只在Python 2.7跑過,版本3應該會有問題
。還很多沒考量的......





0 意見:

搜尋此網誌

總網頁瀏覽量

TK呱呱

Made with by TK