QT实现TCP网络聊天室

Netany ·
更新时间:2024-11-13
· 1017 次阅读

本文实例为大家分享了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(); }

最终实现效果:



tcp 聊天室

需要 登录 后方可回复, 如果你还没有账号请 注册新账号