网站空间地址查询,2022年中国企业500强榜单,营销推广方案范文,网站正能量网站不用下载直接进入#x1f64c;秋名山码民的主页 #x1f602;oi退役选手#xff0c;Java、大数据、单片机、IoT均有所涉猎#xff0c;热爱技术#xff0c;技术无罪 #x1f389;欢迎关注#x1f50e;点赞#x1f44d;收藏⭐️留言#x1f4dd; 获取源码#xff0c;添加WX 目录 前言一… 秋名山码民的主页 oi退役选手Java、大数据、单片机、IoT均有所涉猎热爱技术技术无罪 欢迎关注点赞收藏⭐️留言 获取源码添加WX 目录 前言一、主界面和聊天窗口二、UDP聊天三、TCP文件传输server类Clint类 最后 前言
QQ是一款优秀的聊天软件本文将提供主要代码和思路来实现一个类似于QQ群聊的网络聊天软件大致有以下俩个功能
采用qt5编写实现基于UDP的文本聊天功能和基于TCP的文件传输功能
基本聊天会话功能 通过获取每一个用户运行该程序的时候发送广播来实现不仅用户登录的时候进行广播退出、发送信息的时候都使用UDP广播来告知用户每个用户的聊天窗口为一个端点 文件传输功能实现 文件的传输采用TCP来实现用C/S架构 主界面选中要发送的文件单击传输打开发送文件对话框当用户单击发送的时候程序通过UDP广播给接收端接收端在收到文件的UDP消息后弹出提示框是否接收如果接收先创建一个TCP通信客户端双方进行TCP通信如果拒绝再通过UDP广播告知发送端 一、主界面和聊天窗口 #ifndef DRAWER_H
#define DRAWER_H#include QToolBox
#include QToolButton
#include QWidget
#include myqq.hclass Drawer : public QToolBox
{
public:Drawer();
private:QToolButton *toolBtn1;//聊天对象窗口指针QWidget *chatWidget1;private slots:// 显示聊天对象窗口void showChatWidget1();MyQQ *myqq;};#endif // DRAWER_HsetWindowTitle(tr(My QQ v01));setWindowIcon(QPixmap(:/images/R-C.jpg));toolBtn1 new QToolButton;toolBtn1-setText(tr(冰雪奇缘));toolBtn1-setIcon(QPixmap(:/images/girl1.jpg));toolBtn1-setAutoRaise(true); //设置toolBtn1在显示时自动提升使得按钮外观更加立体感。toolBtn1-setToolButtonStyle(Qt::ToolButtonTextBesideIcon); //设置toolBtn1的按钮样式为图标在文本旁边的形式。// 将显示函数与抽屉盒中相对应的用户按钮进行绑定//connect(toolBtn1,SIGNAL(clicked()),this,SLOT(showChatWidget1()));//connect(toolBtn1, QToolButton::clicked, this, QToolBox::showChatWidget1);connect(toolBtn1, QToolButton::clicked, this, Drawer::showChatWidget1);二、UDP聊天
原理如果要进行聊天则首先要获取所有登录用户的信息这个功能是通过在每一个用户运行该程序时发送广播实现的不仅用户登录时要进行广播而且在用户退出、发送消息时都使用UDP广播来告知所有用户。
#ifndef SERVER_H
#define SERVER_H#include QDialog
#include QFile
#include QTcpServer
#include QTimenamespace Ui {
class Server;
}class Server : public QDialog
{Q_OBJECTpublic:explicit Server(QWidget *parent nullptr);~Server();void initSrv(); // 初始化服务器void refused(); // 关闭服务器protected:void closeEvent(QCloseEvent *);void updClntProgress(qint64 numBytes);private slots:void on_Server_accepted();void sendMsg(); //发送数据void updclntProgress(qint64 numBytes); // 更新进度条void on_sOpenBtn_clicked();void on_sSendBtn_clicked();void on_sCloseBtn_clicked();private:Ui::Server *ui;qint16 tPort;QTcpServer *tSrv;QString fileName;QString theFileName;QFile *locFile; //待发送的文件qint64 totalBytes; //总共要发送的qint64 bytesWritten; //已发送的qint64 bytesTobeWrite; //待发送的qint64 payloadSize; //被初始化为一个常量QByteArray outBlock; // 缓存一次的QTcpSocket *clntConn;QTime time;signals:void sendFileName(QString fileName);
};#endif // SERVER_H
#include server.h
#include ui_server.h#include QFile
#includeQTcpServer
#includeQTcpSocket
#includeQMessageBox
#include QFileDialog
#includeQDebugServer::Server(QWidget *parent) :QDialog(parent),ui(new Ui::Server)
{ui-setupUi(this);setFixedSize(400,207);tPort 5555;tSrv new QTcpServer(this);connect(tSrv,QTcpServer::newConnection,this,Server::sendMsg);initSrv();
}void Server::initSrv()
{payloadSize 64*1024;totalBytes 0;bytesWritten 0;ui-sOpenBtn-setEnabled(true);ui-sSendBtn-setEnabled(false);tSrv-close();
}// 发送数据
void Server::sendMsg()
{ui-sSendBtn-setEnabled(false);clntConn tSrv-nextPendingConnection();connect(clntConn,SIGNAL(bytesWritten(gint64)),this,SLOT(updCIntProgress(qint64)));ui-sStatusLabel-setText(tr(开始传送文件 号1 !).arg(theFileName));locFile new QFile(fileName);if(!locFile-open((QFile::ReadOnly))){QMessageBox::warning(this,tr(应用程序), tr(无法读取文件号1: n各2).arg(fileName).arg(locFile-errorString()));return;}totalBytes locFile-size();QDataStream sendOut(outBlock, QIODevice::WriteOnly);sendOut.setVersion(QDataStream::Qt_4_7);time.start();QString curFile fileName.right(fileName.size() - fileName.lastIndexOf(/) - 1);sendOut qint64(0) qint64((outBlock.size() - sizeof(qint64)*2));bytesTobeWrite totalBytes - clntConn-write(outBlock);outBlock.reserve(0);
}// 更新进度条
void Server::updClntProgress(qint64 numBytes)
{// 防止传输大文件产生冻结qApp-processEvents();bytesWritten (int)numBytes;if(bytesTobeWrite 0){outBlock locFile-read(qMin(bytesTobeWrite,payloadSize));bytesTobeWrite - (int)clntConn-write(outBlock);outBlock.resize(0);} else{locFile-close();}ui-progressBar-setMaximum(totalBytes);ui-progressBar-setValue(bytesWritten);float useTime time.elapsed();double speed bytesWritten / useTime;ui-sStatusLabel-setText(tr(已发送 %1MB (%2MB/s)\n 共%3MB 已用时%4s\n 估计剩余时间%5秒).arg(bytesWritten/(1024*1024)).arg(bytesWritten / (1024*1024)).arg(speed*1000 / (1024*1024),0,f,0).arg(totalBytes / (1024 * 1024)).arg(useTime/1000,0,f,0).arg(totalBytes/speed/1000 - useTime/1000,0,f,0));if(bytesWritten totalBytes){locFile-close();tSrv-close();ui-sStatusLabel-setText(tr(传送文件 %1 成功).arg(theFileName));}}
Server::~Server()
{delete ui;
}void Server::on_sOpenBtn_clicked()
{fileName QFileDialog::getOpenFileName(this);if(!fileName.isEmpty()){theFileName fileName.right(fileName.size() - fileName.lastIndexOf(/)-1);ui-sStatusLabel-setText(tr(要发送的文件为%1).arg(theFileName));ui-sOpenBtn-setEnabled(false);ui-sSendBtn-setEnabled(true);}
}void Server::on_sSendBtn_clicked()
{if(!tSrv-listen(QHostAddress::Any,tPort)){qDebug() tSrv -errorString();close();return;}ui-sStatusLabel-setText(等待……);emit sendFileName(theFileName);
}void Server::on_sCloseBtn_clicked()
{if(tSrv-isListening()){tSrv-close();if(locFile-isOpen())locFile-close();clntConn-abort();}close();
}void Server::closeEvent(QCloseEvent *)
{on_sCloseBtn_clicked();
}void Server::refused()
{tSrv-close();ui-sStatusLabel-setText(tr(对方拒绝));
}三、TCP文件传输
文件的传输采用TCP来实现用C/S客户端/服务器方式创建俩个新类client和server类
server类 #ifndef SERVER_H
#define SERVER_H#include QDialog
#include QFile
#include QTcpServer
#include QTimenamespace Ui {
class Server;
}class Server : public QDialog
{Q_OBJECTpublic:explicit Server(QWidget *parent nullptr);~Server();void initSrv(); // 初始化服务器void refused(); // 关闭服务器protected:void closeEvent(QCloseEvent *);void updClntProgress(qint64 numBytes);private slots:void on_Server_accepted();void sendMsg(); //发送数据void updclntProgress(qint64 numBytes); // 更新进度条void on_sOpenBtn_clicked();void on_sSendBtn_clicked();void on_sCloseBtn_clicked();private:Ui::Server *ui;qint16 tPort;QTcpServer *tSrv;QString fileName;QString theFileName;QFile *locFile; //待发送的文件qint64 totalBytes; //总共要发送的qint64 bytesWritten; //已发送的qint64 bytesTobeWrite; //待发送的qint64 payloadSize; //被初始化为一个常量QByteArray outBlock; // 缓存一次的QTcpSocket *clntConn;QTime time;signals:void sendFileName(QString fileName);
};#endif // SERVER_H
#include server.h
#include ui_server.h#include QFile
#includeQTcpServer
#includeQTcpSocket
#includeQMessageBox
#include QFileDialog
#includeQDebugServer::Server(QWidget *parent) :QDialog(parent),ui(new Ui::Server)
{ui-setupUi(this);setFixedSize(400,207);tPort 5555;tSrv new QTcpServer(this);connect(tSrv,QTcpServer::newConnection,this,Server::sendMsg);initSrv();
}void Server::initSrv()
{payloadSize 64*1024;totalBytes 0;bytesWritten 0;ui-sOpenBtn-setEnabled(true);ui-sSendBtn-setEnabled(false);tSrv-close();
}// 发送数据
void Server::sendMsg()
{ui-sSendBtn-setEnabled(false);clntConn tSrv-nextPendingConnection();connect(clntConn,SIGNAL(bytesWritten(gint64)),this,SLOT(updCIntProgress(qint64)));ui-sStatusLabel-setText(tr(开始传送文件 号1 !).arg(theFileName));locFile new QFile(fileName);if(!locFile-open((QFile::ReadOnly))){QMessageBox::warning(this,tr(应用程序), tr(无法读取文件号1: n各2).arg(fileName).arg(locFile-errorString()));return;}totalBytes locFile-size();QDataStream sendOut(outBlock, QIODevice::WriteOnly);sendOut.setVersion(QDataStream::Qt_4_7);time.start();QString curFile fileName.right(fileName.size() - fileName.lastIndexOf(/) - 1);sendOut qint64(0) qint64((outBlock.size() - sizeof(qint64)*2));bytesTobeWrite totalBytes - clntConn-write(outBlock);outBlock.reserve(0);
}// 更新进度条
void Server::updClntProgress(qint64 numBytes)
{// 防止传输大文件产生冻结qApp-processEvents();bytesWritten (int)numBytes;if(bytesTobeWrite 0){outBlock locFile-read(qMin(bytesTobeWrite,payloadSize));bytesTobeWrite - (int)clntConn-write(outBlock);outBlock.resize(0);} else{locFile-close();}ui-progressBar-setMaximum(totalBytes);ui-progressBar-setValue(bytesWritten);float useTime time.elapsed();double speed bytesWritten / useTime;ui-sStatusLabel-setText(tr(已发送 %1MB (%2MB/s)\n 共%3MB 已用时%4s\n 估计剩余时间%5秒).arg(bytesWritten/(1024*1024)).arg(bytesWritten / (1024*1024)).arg(speed*1000 / (1024*1024),0,f,0).arg(totalBytes / (1024 * 1024)).arg(useTime/1000,0,f,0).arg(totalBytes/speed/1000 - useTime/1000,0,f,0));if(bytesWritten totalBytes){locFile-close();tSrv-close();ui-sStatusLabel-setText(tr(传送文件 %1 成功).arg(theFileName));}}
Server::~Server()
{delete ui;
}void Server::on_sOpenBtn_clicked()
{fileName QFileDialog::getOpenFileName(this);if(!fileName.isEmpty()){theFileName fileName.right(fileName.size() - fileName.lastIndexOf(/)-1);ui-sStatusLabel-setText(tr(要发送的文件为%1).arg(theFileName));ui-sOpenBtn-setEnabled(false);ui-sSendBtn-setEnabled(true);}
}void Server::on_sSendBtn_clicked()
{if(!tSrv-listen(QHostAddress::Any,tPort)){qDebug() tSrv -errorString();close();return;}ui-sStatusLabel-setText(等待……);emit sendFileName(theFileName);
}void Server::on_sCloseBtn_clicked()
{if(tSrv-isListening()){tSrv-close();if(locFile-isOpen())locFile-close();clntConn-abort();}close();
}void Server::closeEvent(QCloseEvent *)
{on_sCloseBtn_clicked();
}void Server::refused()
{tSrv-close();ui-sStatusLabel-setText(tr(对方拒绝));
}
Clint类
TCP客户端类用于接收文件。
#ifndef CLIENT_H
#define CLIENT_H#include QDialog
#include QHostAddress
#include QFile
#include QTime
#include QTcpSocketnamespace Ui {
class client;
}class client : public QDialog
{Q_OBJECTpublic:explicit client(QWidget *parent nullptr);~client();void setHostAddr(QHostAddress addr);void setFileName(QString name);protected:void closeEvent(QCloseEvent *);private:Ui::client *ui;QTcpSocket *tClnt;quint16 blockSize;QHostAddress hostAddr;qint16 tPort;qint64 totalBytes;qint64 bytesReceived;qint64 fileNameSize;QString fileName;QFile *locFile;QByteArray inBlock;QTime time;private slots:void newConn(); // 连接到服务器void readMsg(); // 读取文件数据
// void displayErr(QAbstractSocket::SocketError); // 显示错误信息void on_cCancleBtn_clicked();void on_cCloseBtn_clicked();
};#endif // CLIENT_H
#include client.h
#include ui_client.h
#include QDebug
#include QMessageBox
#include QTimeclient::client(QWidget *parent) :QDialog(parent),ui(new Ui::client)
{ui-setupUi(this);setFixedSize(400,190);totalBytes 0;bytesReceived 0;fileNameSize 0;tClnt new QTcpSocket(this);tPort 5555;connect(tClnt, QTcpSocket::readyRead, this, client::readMsg);}// 连接服务器
void client::newConn()
{blockSize 0;tClnt-abort();tClnt-connectToHost(hostAddr,tPort);time.start();
}// 发送文件
void client::readMsg()
{QDataStream in(tClnt);in.setVersion(QDataStream::Qt_4_7);float useTime time.elapsed();if (bytesReceived sizeof(qint64)*2){if ((tClnt-bytesAvailable() sizeof(qint64)*2) (fileNameSize 0)){intotalBytesfileNameSize;bytesReceived sizeof(qint64)*2;}if((tClnt-bytesAvailable() fileNameSize) (fileNameSize ! 0)){infileName;bytesReceived fileNameSize;if(!locFile-open(QFile::WriteOnly)){QMessageBox::warning(this,tr(应用程序),tr(无法读取文件%1:\n%2.).arg(fileName).arg(locFile-errorString()));}return;}else{return;}}if (bytesReceived totalBytes){bytesReceived tClnt-bytesAvailable();inBlock tClnt-readAll();locFile-write(inBlock);inBlock.resize(0);}ui-progressBar-setMaximum(totalBytes);ui-progressBar-setValue(bytesReceived);double speed bytesReceived / useTime;ui-label_2-setText(tr(已接收 %1MB (%2MB/s)\n 共%3MB 已用时%4s\n 估计剩余时间%5秒).arg(bytesReceived/(1024*1024)).arg(speed*1000 / (1024*1024),0,f,0).arg(totalBytes / (1024 * 1024)).arg(useTime/1000,0,f,0).arg(totalBytes/speed/1000 - useTime/1000,0,f,0));if(bytesReceived totalBytes){locFile-close();tClnt-close();ui-label-setText(tr(接收文件 %1 成功).arg(fileName));}
}
client::~client()
{delete ui;
}void client::on_cCancleBtn_clicked()
{tClnt-abort();if(locFile-isOpen())locFile-close();}void client::on_cCloseBtn_clicked()
{tClnt-abort();if(locFile-isOpen())locFile-close();close();
}void client::closeEvent(QCloseEvent *)
{on_cCloseBtn_clicked();
}
最后
至此已完成读者还可根据自己所需来添加一些拓展功能更改字体、字号和颜色等等……如果本文对你有所帮助还请三连支持一下博主