您好,登錄后才能下訂單哦!
今天小編給大家分享一下怎么用QT實現TCP網絡聊天室的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
serverdialog.h
#ifndef SERVERDIALOG_H #define SERVERDIALOG_H #include <QDialog> #include <QTcpServer> #include <QTcpSocket> #include <QDebug> #include <QTimer> namespace Ui { class ServerDialog; } class ServerDialog : public QDialog { Q_OBJECT public: explicit ServerDialog(QWidget *parent = 0); ~ServerDialog(); private slots: //創建服務器按鈕對應的槽函數 void on_pushButton_clicked(); //響應客戶端連接請求的槽函數 void onNewConnection(); //接收客戶端聊天消息的槽函數 void onReadyRead(); //轉發聊天消息給其它客戶端的槽函數 void sendMessage(const QByteArray&); //定時器檢查客戶端套接字是否為正常連接狀態的槽函數 void onTimeout(void); private: Ui::ServerDialog *ui; QTcpServer tcpServer;//TCP服務器 quint16 port;//服務器端口,quint16-->unsigned short QList<QTcpSocket*> tcpClientList;//容器:保存和客戶端通信的套接字 QTimer timer;//定時器,定時檢查容器中和客戶端通信的套接字是否為正常連接狀態 }; #endif // SERVERDIALOG_H
serverdialog.cpp
#include "serverdialog.h" #include "ui_serverdialog.h" ServerDialog::ServerDialog(QWidget *parent) : QDialog(parent), ui(new Ui::ServerDialog) { ui->setupUi(this); } ServerDialog::~ServerDialog() { delete ui; } //創建服務器按鈕對應的槽函數 void ServerDialog::on_pushButton_clicked() { //獲取服務器端口 port = ui->lineEdit->text().toShort(); //設置監聽服務器的IP和端口 //QHostAddress::Any ==> QHostAddress("0.0.0.0"); if(tcpServer.listen(QHostAddress::Any,port)==false){ qDebug() << "創建服務器失敗"; return; } else{ qDebug() << "創建服務器成功"; //當有客戶端向服務器發送連接請求時,發送信號newConnection connect(&tcpServer,SIGNAL(newConnection()), this,SLOT(onNewConnection())); //禁用端口輸入和創建服務器按鈕 ui->lineEdit->setEnabled(false); ui->pushButton->setEnabled(false); //定時器到時發送信號:timeout connect(&timer,SIGNAL(timeout()),this,SLOT(onTimeout())); //開啟定時器,每隔3秒檢查一次 timer.start(3000); } } //響應客戶端連接請求的槽函數 void ServerDialog::onNewConnection() { //獲取和客戶端通信的套接字 QTcpSocket* tcpClient = tcpServer.nextPendingConnection(); //保存套接字到容器中 tcpClientList.append(tcpClient); //當客戶端給服務器發送消息時,tcpClient發送信號readyRead connect(tcpClient,SIGNAL(readyRead()), this,SLOT(onReadyRead())); } //接收客戶端聊天消息的槽函數 void ServerDialog::onReadyRead() { //遍歷檢查哪個客戶端有消息 for(int i=0;i<tcpClientList.size();i++){ //at(i):獲取容器中第i套接字(QTcpSocket*) //bytesAvailable:獲取當前套接字等待讀取消息的字節數,如果為0表示沒有消息,如果 //大于0說明有消息. if(tcpClientList.at(i)->bytesAvailable()){ //讀取消息并保存 QByteArray buf = tcpClientList.at(i)->readAll(); //顯示消息 ui->listWidget->addItem(buf); //回滾到最底部(最新消息) ui->listWidget->scrollToBottom(); //轉發消息給其它客戶端 sendMessage(buf); } } } //轉發聊天消息給其它客戶端的槽函數 void ServerDialog::sendMessage(const QByteArray& msg) { for(int i=0;i<tcpClientList.size();i++){ tcpClientList.at(i)->write(msg); } } //定時器檢查客戶端套接字是否為正常連接狀態的槽函數 void ServerDialog::onTimeout(void) { for(int i=0;i<tcpClientList.size();i++){ //state():獲取第i個套接字的連接狀態 //UnconnectedState:表示未連接(斷開連接) if(tcpClientList.at(i)->state() == QAbstractSocket::UnconnectedState){ //從容器中將斷開連接的套接字移除 tcpClientList.removeAt(i); --i; } } }
main.cpp
#include "serverdialog.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); ServerDialog w; w.show(); return a.exec(); }
clientdialog:
#ifndef CLIENTDIALOG_H #define CLIENTDIALOG_H #include <QDialog> //QT += network #include <QTcpSocket> #include <QHostAddress> #include <QMessageBox> namespace Ui { class ClientDialog; } class ClientDialog : public QDialog { Q_OBJECT public: explicit ClientDialog(QWidget *parent = 0); ~ClientDialog(); private slots: //發送按鈕對應的槽函數 void on_sendButton_clicked(); //連接服務器按鈕對應的槽函數 void on_connectButton_clicked(); //和服務器連接成功時執行的槽函數 void onConnected(void); //和服務器斷開連接時執行的槽函數 void onDisconnected(void); //接收服務器轉發聊天消息的槽函數 void onReadyRead(void); //網絡通信異常時執行的槽函數 void onError(void); private: Ui::ClientDialog *ui; bool status;//客戶端狀態標記,true:在線,false:離線狀態 QTcpSocket tcpSocket;//和服務器通信的tcp套接字 QHostAddress serverIp;//服務器地址 quint16 serverPort;//服務器端口 QString username;//聊天室昵稱 }; #endif // CLIENTDIALOG_H
clientdialog.cpp
#include "clientdialog.h" #include "ui_clientdialog.h" ClientDialog::ClientDialog(QWidget *parent) : QDialog(parent), ui(new Ui::ClientDialog) { ui->setupUi(this); status = false; //和服務器連接成功時,tcpSocket發送信號:connected connect(&tcpSocket,SIGNAL(connected()), this,SLOT(onConnected())); //和服務器斷開連接時,tcpSocket發送信號:disconnected connect(&tcpSocket,SIGNAL(disconnected()), this,SLOT(onDisconnected())); //收到聊天消息時,tcpSocket發送信號:readyRead connect(&tcpSocket,SIGNAL(readyRead()), this,SLOT(onReadyRead())); //網絡通信異常時,tcpSocket發送信號:error connect(&tcpSocket,SIGNAL(error(QAbstractSocket::SocketError)), this,SLOT(onError())); } ClientDialog::~ClientDialog() { delete ui; } //發送按鈕對應的槽函數 void ClientDialog::on_sendButton_clicked() { //獲取用戶輸入的消息 QString msg = ui->messageEdit->text(); if(msg == ""){ return; } msg = username + ":" + msg; //發送消息 tcpSocket.write(msg.toUtf8()); //清空已輸入的消息 ui->messageEdit->clear(); } //連接服務器按鈕對應的槽函數 void ClientDialog::on_connectButton_clicked() { if(status == false){//如果當前是離線狀態,則連接服務器 //獲取服務器IP if(serverIp.setAddress(ui->serverIpEdit->text())==false){ //critical():表示錯誤的消息提示框 QMessageBox::critical(this,"Error","IP地址錯誤"); return; } //獲取服務器端口 serverPort = ui->serverportEdit->text().toShort(); if(serverPort < 1024){ QMessageBox::critical(this,"Error","端口格式錯誤"); return; } //獲取聊天室昵稱 username = ui->usernameEdit->text(); if(username == ""){ QMessageBox::critical(this,"Error","聊天室昵稱不能為空"); return; } //向服務器發送連接請求: //如果成功,發送信號:connected; //如果失敗,發送信號:error tcpSocket.connectToHost(serverIp,serverPort); } else{//如果當前是在線狀態,則斷開和服務器連接 //向服務器發送離開聊天室的消息 QString msg = username + ":離開了聊天室"; //toUtf8():將QString(unicode)轉換QByteArray(utf-8) tcpSocket.write(msg.toUtf8()); //斷開連接 //斷開后發送信號:disconnected tcpSocket.disconnectFromHost(); } } //和服務器連接成功時執行的槽函數 void ClientDialog::onConnected(void) { status = true;//設置狀態標記:在線 ui->sendButton->setEnabled(true);//恢復"發送"按鈕為正常可用狀態 ui->serverIpEdit->setEnabled(false);//禁用ip輸入 ui->serverportEdit->setEnabled(false);//禁用端口輸入 ui->usernameEdit->setEnabled(false);//禁用昵稱輸入 ui->connectButton->setText("離開聊天室");//修改連接服務器按鈕文本 //向服務器發送進入聊天室提示消息 QString msg = username + ":進入了聊天室"; //toUtf8():將QString(unicode)轉換QByteArray(utf-8) tcpSocket.write(msg.toUtf8()); } //和服務器斷開連接時執行的槽函數 void ClientDialog::onDisconnected(void) { status = false;//設置離線狀態 ui->sendButton->setEnabled(false);//禁用"發送"按鈕 ui->serverIpEdit->setEnabled(true);//恢復ip輸入 ui->serverportEdit->setEnabled(true);//恢復端口輸入 ui->usernameEdit->setEnabled(true);//恢復昵稱輸入 ui->connectButton->setText("連接服務器");//修改離開聊天室按鈕文本 } //接收服務器轉發聊天消息的槽函數 void ClientDialog::onReadyRead(void) { //bytesAvailable():獲取等待讀取消息的字節數 if(tcpSocket.bytesAvailable()){ //讀取消息 QByteArray buf = tcpSocket.readAll(); //顯示消息到界面 ui->listWidget->addItem(buf); ui->listWidget->scrollToBottom(); } } //網絡通信異常時執行的槽函數 void ClientDialog::onError(void) { //errorString():獲取網絡通信異常原因的字符串 QMessageBox::critical(this,"Error",tcpSocket.errorString()); }
main.cpp
#include "clientdialog.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); ClientDialog w; w.show(); return a.exec(); }
最終實現效果:
以上就是“怎么用QT實現TCP網絡聊天室”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。