基于TCP的网络聊天程序


基于TCP的网络聊天程序


  • 下图是最后效果图(因为是刚做好,还没来的及修改小细节,不过这都是小事);
    基于TCP的网络聊天程序_第1张图片
  • 在说明之前需要说明一点关于信号与槽的Qt常识
    • signals: 只声明,不定义! 手动定义的信号,使用 emit ,由自己手动触发;
    • slots:定义的槽可以通过自己定义的信号或者系统信号来被动调用;

好了,我们现在进入正题


1. 程序框架(数据传输的过程):

  首先,我来说明下整个大框架。我认为,在本次编程过程中,最重要的部分就是他了,没有之一!
  为了便于说明下面大家先看这张图,之后的说明都围绕这张图来说明:

基于TCP的网络聊天程序_第2张图片

  • 客户端方面:首先,客户端方面包含两部分。一个是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通信原理和实践

你可能感兴趣的:(Qt)