基於TCP的網絡聊天程序


基於TCP的網絡聊天程序


  • 下圖是最後效果圖(因爲是剛做好,還沒來的及修改小細節,不過這都是小事);
    效果圖
  • 在說明之前需要說明一點關於信號與槽的Qt常識
    • signals: 只聲明,不定義! 手動定義的信號,使用 emit ,由自己手動觸發;
    • slots:定義的槽可以通過自己定義的信號或者系統信號來被動調用;

好了,我們現在進入正題


1. 程序框架(數據傳輸的過程):

  首先,我來說明下整個大框架。我認爲,在本次編程過程中,最重要的部分就是他了,沒有之一!
  爲了便於說明下面大家先看這張圖,之後的說明都圍繞這張圖來說明:

  • 客戶端方面:首先,客戶端方面包含兩部分。一個是ClientUI,用於佈置客戶端界面;另一個是從QTcpSocket繼承來的子類ClientSocket,通過 ClientSocket + ServerIP + Port 連接到服務器, 成功連接後就可以通過ClientSocket 和服務器端進行通信了(發送數據和接受數據)。ClientUI 和ClientSocket 之間通過信號與槽進行信息傳遞(接收:ClientSocket從服務器接收到數據後,通過信號與槽傳遞給ClientUI,然後ClientUI將信息顯示出來;發送:點擊Send按鈕後,ClientUI將數據通過信號與槽傳遞給ClientSocket,ClientSocket將信息傳輸給服務器端)。
  • 服務器端方面:服務器端方面稍複雜一點。一個用於佈置服務器端界面的ServerUI;一個是從QTcpServer繼承來的子類Server,Server 和ServerUI 之間傳輸數據與 ClientSocket 和 ClientUI 之間很類似,不再囉嗦,另外Server 還包含一個Socket的列表,用來記錄連接到該服務器的socket信息。當有新信息收到後,可以通過該列表更新所有連接到該服務器端的客戶端。在我看來,Server端就相當於一個信息中轉站,任意一個客戶端都可以通過Server與其他的客戶端進行通信。
  • 客戶端的ClientSocket和服務器端Socket列表中某一socket連接,進行通信。
  • 其實明白了以上內容就可以自己動手開始寫了,下面信號與槽接口有需要可作爲參考。

2. 設計UI,確定每個部件所需要實現的功能。

UI的編寫很簡單,只要寫過一個基本就沒什麼問題,如有需要可以參考我之前的一篇博客Qt實例–計算圓的面積.

3. 根據實現功能設計信號與槽:

a.客戶端


//ClientUI:
signals:
    void sendMsg(QString);                       //告訴ClientSocket有活幹了
    void connectServer(QString,QString);         //讓ClientSocket連接到服務器
    void disconnectServer();                     //讓ClientSocket從服務器斷開

public slots:
    void slotSendMsg();                          //UI上send按鈕被點擊後觸發。功能:對信息進行簡單處理,發出sendMsg(QString)信號;
    void slotSwitch();                           //UI上最下方按鈕被點擊後觸發。
                                                 //功能:根據是否已連接Server作出不同反應。
                                                 //若已連接,發出disconnectServer()信號,若未連接,發出connectServer(QString,QString);
    void slotConnected();                        //若ClientSocket成功連接服務器後觸發。 功能:將UI上最下方按鈕文本改成”leave“。
    void slotdisconnected();                     //若ClientSocket斷開服務器後觸發。 功能:將UI上最下方按鈕文本改成”enter“。
    void slotupdateClient(QString);              //當ClientSocket發出updateClient()信號時被觸發。 功能:將新信息顯出來。

//ClientSocket
signals:
     void updateClient(QString);                 //讓ClientUI更新新信息;

public slots:
     void slotsendMsg(QString);                  //當ClientUI發出sendMsg(QString)信號後觸發。功能:向Server發送數據
     void slotconnectServer(QString,QString);    //當ClientUI發出connectServer(QString,QString)信號後觸發。功能:嘗試連接服務器。
     void slotdisconnectServer();                //當ClientUI發出disconnectServer()信號後觸發。功能:嘗試斷開與服務器的連接
     void slotdataReceive();                     //當ClientSocket檢測到有新數據到達時觸發。功能:接收數據並處理,然後觸發updateClient(QString)信號。

b.服務器端


//ServerUI
signals:
    void createServer();                         //功能:觸發slotCreateServer();
    void closeServer();                          //功能:觸發Server的SlotClost();

public slots:
    void slotServerSwitch();                     //當服務器端下方按鈕被點擊時觸發。
                                                 //功能:根據是否已經創建服務器,採取不同的方式運行
                                                 //若已建好服務器,則發起closeServer()信號
                                                 //否則,發起createServer()信號
    void slotupdateServerUI(QString);            //當updateServerUI(QString)信號發出後被觸發。  功能:將收到信息顯示到服務器端
    void slotCreateServer();                     //當createServer()信號發出時被觸發。           功能:創建一個Server

//Server    
signals:
    void updateServerUI(QString);                //功能:觸發ServerUI的slotupdateServerUI(QString);

private slots:
    void updateClient(QString);                  //當Client的updateServer(QString)信號發出後被觸發。功能:向所有客戶端寫數據。發出updateServerUI(QString)信號。
    void slotdisconnect(int);                    //當Client的disconnect(int)信號發出後被觸發。      功能:從server的client列表中將特定client刪除。
    void slotClose();                            //當ServerUI發出closeServer()信號後被觸發。        功能:斷開所有連接,清空client列表,並析構當前Server。
protected:
    void incomingConnection(qintptr);            //重載函數
                                                 //當有socket試圖連接時被觸發,不需要自己寫connect()來連接。
                                                 //另外需注意的一點是該函數的參數,Qt4參數是int,Qt5是qintptr。寫錯了永遠不會被調用。。。小心

//Client    
signals:
    void updateServer(QString);                  //更新服務器
    void disconnect(int);                        //發出信號讓服務器從client列表中移除該Client,參數爲該Client的套接字描述符(唯一描述一個socket)。

private slots:
    void dataReceive();                          //當有數據可讀時被觸發,功能:接收並處理數據,然後發出updateServer(QString)信號。
    void slotdisconnect();                       //Client被斷開時被觸發。功能:獲得該Client的套接字描述符,併發出disconnect(int)信號

4 我的源碼

我的源碼放在github上了,大家有需要可以直接去看我的小項目chatroom

5 推薦閱讀:

Socket通信原理和實踐

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章