亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

QT基于TCP如何實現網絡聊天室程序

發布時間:2022-08-23 17:23:55 來源:億速云 閱讀:179 作者:iii 欄目:開發技術

今天小編給大家分享一下QT基于TCP如何實現網絡聊天室程序的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

TCP與UDP的差別如圖:

QT基于TCP如何實現網絡聊天室程序

一、TCP工作原理

如下圖所示,TCP能夠為應用程序提供可靠的通信連接,使一臺計算機發出的字節流無差錯 地送達網絡上的其他計算機。因此,對可靠性要求高的數據通信系統往往使用TCP傳輸數據,但在正式收發數據前,通信雙方必須首先建立連接。

QT基于TCP如何實現網絡聊天室程序

二、TCP編程模型

下面介紹基于TCP的經典編程模型,TCP客戶端與服務器間的交互時序如下圖所示:

QT基于TCP如何實現網絡聊天室程序

三、TCP服務器端編程實例

TCP服務器端的具體實現如下:

建立工程TcpServer.pro,文件代碼如下。

(1)頭文件“tcpserver.h”中聲明了需要的各種控件,TcpServer繼承自QDialog,實現了服務器端的對話框顯示與控制。其具體代碼如下:

#include <QDialog> 
#include <QListWidget> 
#include <QLabel> 
#include <QLineEdit> 
#include <QPushButton> 
#include <QGridLayout> 
class TcpServer : public QDialog 
{ 
Q_OBJECT 
public: 
TcpServer(QWidget *parent = 0,Qt::WindowFlags f=0); 
~TcpServer(); 
private: 
QListWidget *ContentListWidget; 
QLabel *PortLabel; 
QLineEdit *PortLineEdit; 
QPushButton *CreateBtn; 
QGridLayout *mainLayout; 
};

(2)在源文件“tcpserver.cpp”中,TcpServer類的構造函數主要實現窗體各控件的創建、布局等,其具體代碼如下:

#include "tcpserver.h" 
TcpServer::TcpServer(QWidget *parent,Qt::WindowFlags f) : QDialog(parent,f) 
{ 
setWindowTitle(tr("TCP Server")); 
ContentListWidget = new QListWidget; 
PortLabel = new QLabel(tr("端口:")); 
PortLineEdit = new QLineEdit; 
CreateBtn = new QPushButton(tr("創建聊天室")); 
mainLayout = new QGridLayout(this); 
mainLayout->addWidget(ContentListWidget,0,0,1,2); 
mainLayout->addWidget(PortLabel,1,0); 
mainLayout->addWidget(PortLineEdit,1,1); 
mainLayout->addWidget(CreateBtn,2,0,1,2); 
}

(3)服務器端界面如下圖所示:

QT基于TCP如何實現網絡聊天室程序

以上完成了服務器端界面的設計,下面將詳細完成聊天室的服務器端功能。

(1)在工程文件“TcpServer.pro”中添加如下語句:

QT += network 

(2)在工程“TcpServer.pro”中添加C++類文件“tcpclientsocket.h”及“tcpclientsocket.cpp”,TcpClientSocket 繼承自QTcpSocket,創建一個TCP套接字,以便在服務器端實現與客戶端程序的通信。
頭文件“tcpclientsocket.h”的具體代碼如下:

#include <QTcpSocket> 
#include <QObject> 
class TcpClientSocket : public QTcpSocket 
{ 
Q_OBJECT //添加宏(Q_OBJECT)是為了實現信號與槽的通信 
public: 
TcpClientSocket(QObject *parent=0); 
signals: 
void updateClients(QString,int); 
void disconnected(int); 
protected slots: 
void dataReceived(); 
void slotDisconnected(); 
};

(3)在源文件“tcpclientsocket.cpp”中,構造函數(TcpClientSocket)的內容(指定了信號與槽的
連接關系)如下:

#include "tcpclientsocket.h" 
TcpClientSocket::TcpClientSocket(QObject *parent) 
{ 
connect(this,SIGNAL(readyRead()),this,SLOT(dataReceived())); // readyRead()是QIODevice的signal,由 QTcpSocket繼承而來。QIODevice是所有輸入/輸出設備的一個抽象類,其中定義了基本的接口,在Qt中, QTcpSocket也被看成一個QIODevice,readyRead()信號在有數據到來時發出。  
connect(this,SIGNAL(disconnected()),this,SLOT(slotDisconnected())); // disconnected()信號在斷開連接時發出。 
}

在源文件“tcpclientsocket.cpp”中,dataReceived()函數的具體代碼如下:

void TcpClientSocket::dataReceived() 
{ 
while(bytesAvailable()>0) 
{ 
int length = bytesAvailable(); 
char buf[1024]; 
read(buf,length); 
QString msg=buf; 
emit updateClients(msg,length); 
} 
}

在源文件“tcpclientsocket.cpp”中,槽函數slotDisconnected()的具體代碼如下:

void TcpClientSocket::slotDisconnected() 
{ 
emit disconnected(this->socketDescriptor()); 
}

(4)在工程“TcpServer.pro”中添加C++類文件“server.h”及“server.cpp”,Server繼承自QTcpServer,實現一 個TCP協議的服務器。利用QTcpServer,開發者可以監聽到指定端口的TCP連接。其具體代碼如下:

#include <QTcpServer> 
#include <QObject> 
#include "tcpclientsocket.h" //包含TCP的套接字 
class Server : public QTcpServer 
{ 
Q_OBJECT 
//添加宏(Q_OBJECT)是為了實現信號與槽的通信 
public: 
Server(QObject *parent=0,int port=0); 
QList<TcpClientSocket*> tcpClientSocketList; 
signals: 
void updateServer(QString,int); 
public slots: 
void updateClients(QString,int); 
void slotDisconnected(int); 
protected: 
void incomingConnection(int socketDescriptor); 
};

(5)在源文件“server.cpp”中,構造函數(Server)的具體內容如下:

#include "server.h" 
Server::Server(QObject *parent,int port):QTcpServer(parent) 
{ 
listen(QHostAddress::Any,port); 
}

其中,listen(QHostAddress::Any,port)在指定的端口對任意地址進行監聽。
QHostAddress定義了幾種特殊的IP地址,如QHostAddress::Null表示一個空地址;
QHostAddress::LocalHost表示IPv4的本機地址127.0.0.1;
QHostAddress::LocalHostIPv6表示IPv6的本機地址;
QHostAddress::Broadcast表示廣播地址255.255.255.255;
QHostAddress::Any表示IPv4的任意地址0.0.0.0;
QHostAddress::AnyIPv6表示IPv6的任意地址。

在源文件“server.cpp”中,當出現一個新的連接時,QTcpSever觸發incomingConnection()函數,參數

socketDescriptor指定了連接的Socket描述符,其具體代碼如下:

void Server::incomingConnection(int socketDescriptor) 
{ 
TcpClientSocket *tcpClientSocket=new TcpClientSocket(this); //創建一個新的TcpClientSocket與客戶端通信。  
connect(tcpClientSocket,SIGNAL(updateClients(QString,int), this,SLOT(updateClients(QString,int))); //連接TcpClientSocket的updateClients信號。  
connect(tcpClientSocket,SIGNAL(disconnected(int)),this, SLOT(slotDisconnected(int))); //連接 TcpClientSocket的disconnected信號。 
tcpClientSocket->setSocketDescriptor(socketDescriptor); //將新創建的TcpClient Socket的套接字描述符指定為參數socketDescriptor。 
tcpClientSocketList.append(tcpClientSocket); //將tcpClientSocket加入客戶端套接字列表以便管理。 
}

在源文件“server.cpp”中,updateClients()函數將任意客戶端發來的信息進行廣播,保證聊天室的所有成員均能看到其他人的發言。其具體代碼如下:

void Server::updateClients(QString msg,int length) 
{ 
emit updateServer(msg,length); //發出updateServer信號,用來通知服務器對話框更新相應的顯示狀態。
for(int i=0;i<tcpClientSocketList.count();i++) //實現信息的廣播,tcpClientSocketList中保存了所有與服務器相連的TcpClientSocket對象。 
{ 
QTcpSocket *item = tcpClientSocketList.at(i); 
if(item->write(msg.toLatin1(),length)!=length) 
{ 
continue; 
} 
} 
}

在源文件“server.cpp”中,slotDisconnected()函數實現從tcpClientSocketList列表中將斷開連接的
TcpClientSocket對象刪除的功能。其具體代碼如下:

void Server::slotDisconnected(int descriptor) 
{ 
for(int i=0;i<tcpClientSocketList.count();i++) 
{ 
QTcpSocket *item = tcpClientSocketList.at(i); 
if(item->socketDescriptor()==descriptor) 
{ 
tcpClientSocketList.removeAt(i); 
return; 
} 
}
return; 
}

(6)在頭文件“tcpserver.h”中添加如下內容:

#include "server.h" 
private: 
int port; 
Server *server; 
public slots: 
void slotCreateServer(); 
void updateServer(QString,int);

(7)在源文件“tcpserver.cpp”中,在構造函數中添加如下代碼:

port=8010; 
PortLineEdit->setText(QString::number(port)); 
connect(CreateBtn,SIGNAL(clicked()),this,SLOT(slotCreateServer()));

其中,槽函數slotCreateServer()用于創建一個TCP服務器,具體內容如下:

void TcpServer::slotCreateServer() 
{ 
server = new Server(this,port); //創建一個Server對象 
connect(server,SIGNAL(updateServer(QString,int)),this, 
SLOT(updateServer(QString,int))); 
CreateBtn->setEnabled(false); 
}

槽函數updateServer()用于更新服務器上的信息顯示,具體內容如下:

void TcpServer::updateServer(QString msg,int length) 
{ 
ContentListWidget->addItem(msg.left(length)); 
}

(8)此時,工程中添加了很多文件,工程文件中的內容已經被改變,需要重新在工程文件
“TcpServer.pro”中添加:

QT += network 

此時,運行服務器端工程“TcpServer.pro”編譯通過。單擊“創建聊天室”按鈕,便開通了一個TCP聊天室的服務器,如下圖所示:

QT基于TCP如何實現網絡聊天室程序

四、TCP客戶端編程實例

TCP客戶端編程具體步驟如下:

建立工程“TcpClient.pro”,文件代碼如下。

(1)在頭文件“tcpclient.h”中,TcpClient類繼承自QDialog類,聲明了需要的各種控件,其具體代碼如下:

#include <QDialog> 
#include <QListWidget> 
#include <QLineEdit> 
#include <QPushButton> 
#include <QLabel> 
#include <QGridLayout> 
class TcpClient : public QDialog 
{ 
Q_OBJECT 
public: 
TcpClient(QWidget *parent = 0,Qt::WindowFlags f=0); 
~TcpClient(); 
private: 
QListWidget *contentListWidget; 
QLineEdit *sendLineEdit; 
QPushButton *sendBtn; 
QLabel *userNameLabel; 
QLineEdit *userNameLineEdit; 
QLabel *serverIPLabel; 
QLineEdit *serverIPLineEdit; 
QLabel *portLabel; 
QLineEdit *portLineEdit; 
QPushButton *enterBtn; 
QGridLayout *mainLayout; 
};

(2)源文件“tcpclient.cpp”的具體代碼如下:

#include "tcpclient.h" 
TcpClient::TcpClient(QWidget *parent,Qt::WindowFlags f) 
: QDialog(parent,f) 
{ 
setWindowTitle(tr("TCP Client")); 
contentListWidget = new QListWidget; 
sendLineEdit = new QLineEdit; 
sendBtn = new QPushButton(tr("發送")); 
userNameLabel = new QLabel(tr("用戶名:")); 
userNameLineEdit = new QLineEdit; 
serverIPLabel = new QLabel(tr("服務器地址:")); 
serverIPLineEdit = new QLineEdit; 
portLabel = new QLabel(tr("端口:")); 
portLineEdit = new QLineEdit; 
enterBtn= new QPushButton(tr("進入聊天室")); 
mainLayout = new QGridLayout(this); 
mainLayout->addWidget(contentListWidget,0,0,1,2); 
mainLayout->addWidget(sendLineEdit,1,0); 
mainLayout->addWidget(sendBtn,1,1); 
mainLayout->addWidget(userNameLabel,2,0); 
mainLayout->addWidget(userNameLineEdit,2,1); 
mainLayout->addWidget(serverIPLabel,3,0); 
mainLayout->addWidget(serverIPLineEdit,3,1); 
mainLayout->addWidget(portLabel,4,0); 
mainLayout->addWidget(portLineEdit,4,1); 
mainLayout->addWidget(enterBtn,5,0,1,2); 
}

(3)客戶端界面如下圖所示:

QT基于TCP如何實現網絡聊天室程序

以上完成了客戶端界面的設計,下面將完成客戶端的真正聊天功能。

(1)在客戶端工程文件“TcpClient.pro”中添加如下語句:

QT += network 

(2)在頭文件“tcpclient.h”中添加如下代碼:

#include <QHostAddress> 
#include <QTcpSocket> 
private: 
bool status; 
int port; 
QHostAddress *serverIP; 
QString userName; 
QTcpSocket *tcpSocket; 
public slots: 
void slotEnter(); 
void slotConnected(); 
void slotDisconnected(); 
void dataReceived(); 
void slotSend();

(3)在源文件“tcpclient.cpp”中添加頭文件:

#include <QMessageBox> 
#include <QHostInfo>

在其構造函數中添加如下代碼:

status = false; 
port = 8010; 
portLineEdit->setText(QString::number(port)); 
serverIP =new QHostAddress(); 
connect(enterBtn,SIGNAL(clicked()),this,SLOT(slotEnter())); 
connect(sendBtn,SIGNAL(clicked()),this,SLOT(slotSend())); 
sendBtn->setEnabled(false);

在以上代碼中,槽函數slotEnter()實現了進入和離開聊天室的功能。具體代碼如下:

void TcpClient::slotEnter()
{
    if(!status)    //status表示當前的狀態,true表示已經進入聊天室,false表示已經離開聊天室。 這里根據status的狀態決定是執行“進入”還是“離開”的操作。
    {
        /* 完成輸入合法性檢驗 */
        QString ip = serverIPLineEdit->text();
        if(!serverIP->setAddress(ip))//用來判斷給定的IP地址能否被正確解析。
        {
            QMessageBox::information(this,tr("error"),tr("server ip address error!"));
            return;
        }
        if(userNameLineEdit->text()=="")
        {
            QMessageBox::information(this,tr("error"),tr("User name error!"));
            return;
        }
        userName=userNameLineEdit->text();
        /* 創建了一個QTcpSocket類對象,并將信號/槽連接起來 */
        tcpSocket = new QTcpSocket(this);
        connect(tcpSocket,SIGNAL(connected()),this,SLOT (slotConnected()));
        connect(tcpSocket,SIGNAL(disconnected()),this,SLOT (slotDisconnected()));
        connect(tcpSocket,SIGNAL(readyRead()),this,SLOT (dataReceived()));
        tcpSocket->connectToHost(*serverIP,port);    //與TCP服務器端連接,連接成功后發出connected() 信號
        status=true;
    }
    else
    {
        int length=0;
        QString msg=userName+tr(":Leave Chat Room");//構造一條離開聊天室的消息。
        if((length=tcpSocket->write(msg.toLatin1(),msg.length()))!=msg.length())                                                //通知服務器端以上 構造的消息
        {
            return;
        }
        tcpSocket->disconnectFromHost();                    //與服務器斷開連接,斷開連接后發出disconnected()信號。
        status=false; //將status狀態復位
    }
}

在源文件“tcpclient.cpp”中,槽函數slotConnected()為connected()信號的響應槽,當與服務器連接成功后,客戶端構造一條進入聊天室的消息,并通知服務器。其具體代碼如下:

void TcpClient::slotConnected() 
{ 
sendBtn->setEnabled(true); 
enterBtn->setText(tr("離開")); 
int length=0; 
QString msg=userName+tr(":Enter Chat Room"); 
if((length=tcpSocket->write(msg.toLatin1(),msg.length()))!=msg.length()) 
{ 
return; 
} 
}

在源文件“tcpclient.cpp”中,槽函數slotSend()的具體代碼如下:

void TcpClient::slotSend() 
{ 
if(sendLineEdit->text()=="") 
{ 
return; 
}
QString msg=userName+":"+sendLineEdit->text(); 
tcpSocket->write(msg.toLatin1(),msg.length()); 
sendLineEdit->clear(); 
}

在源文件“tcpclient.cpp”中,槽函數slotDisconnected()的具體內容如下:

void TcpClient::slotDisconnected() 
{ 
sendBtn->setEnabled(false); 
enterBtn->setText(tr("進入聊天室")); 
}

當有數據到來時,觸發源文件“tcpclient.cpp”的dataReceived()函數,從套接字中將有效數據取出并顯示,其代碼如下:

void TcpClient::dataReceived() 
{ 
while(tcpSocket->bytesAvailable()>0) 
{ 
QByteArray datagram; 
datagram.resize(tcpSocket->bytesAvailable()); 
tcpSocket->read(datagram.data(),datagram.size()); 
QString msg=datagram.data(); 
contentListWidget->addItem(msg.left(datagram.size())); 
} 
}

(4)此時運行客戶端“TcpClient.pro”工程,結果如下圖所示:

QT基于TCP如何實現網絡聊天室程序

最后,同時運行服務器和客戶端程序,運行結果如下圖所示,這里演示的是系統中登錄了兩 個用戶的狀態。

QT基于TCP如何實現網絡聊天室程序

QT基于TCP如何實現網絡聊天室程序

QT基于TCP如何實現網絡聊天室程序

以上就是“QT基于TCP如何實現網絡聊天室程序”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

平邑县| 云和县| 哈尔滨市| 原阳县| 滦平县| 乾安县| 寿阳县| 思南县| 焦作市| 崇义县| 牡丹江市| 自治县| 上栗县| 邵东县| 张家口市| 凤台县| 桂东县| 湘乡市| 年辖:市辖区| 宿松县| 厦门市| 阜宁县| 延寿县| 菏泽市| 涟水县| 西丰县| 江山市| 读书| 赤城县| 台东县| 兴仁县| 梁山县| 乌恰县| 邵东县| 台中县| 浑源县| 财经| 樟树市| 资兴市| 铜山县| 昭苏县|