原理:
效果图:
代码:
1.服务器端的.h文件
#ifndef SERVERWIDGET_H
#define SERVERWIDGET_H
#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>
#include <QTimer>
#include <QFile>
QT_BEGIN_NAMESPACE
namespace Ui { class serverWidget; }
QT_END_NAMESPACE
class serverWidget : public QWidget
{
Q_OBJECT
public:
serverWidget(QWidget *parent = nullptr);
~serverWidget();
void sendData();
private:
Ui::serverWidget *ui;
QTcpServer *tcpServer;
QTcpSocket *tcpSocket;
QTimer *timer;
QString fileName;
quint16 fileSize;
QFile file;
};
#endif // SERVERWIDGET_H
2.服务器端的.cpp文件
#include "serverwidget.h"
#include "ui_serverwidget.h"
#include <QHostAddress>
#include <QFile>
#include <QFileInfo>
#include <QFileDialog>
serverWidget::serverWidget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::serverWidget)
{
ui->setupUi(this);
tcpServer = new QTcpServer(this);
tcpServer->listen(QHostAddress::Any,8888);
setWindowTitle("服务器端口:8888");
ui->pushButtonOpen->setEnabled(false);
ui->pushButtonSend->setEnabled(false);
connect(tcpServer,&QTcpServer::newConnection,[=](){
tcpSocket = tcpServer->nextPendingConnection();
if(tcpSocket != NULL){
QString ip = tcpSocket->peerName();
quint16 port = tcpSocket->peerPort();
ui->textEdit->setText(QString("客户端:%1 socket:%2").arg(ip).arg(port));
ui->pushButtonOpen->setEnabled(true);
}
connect(tcpSocket,&QTcpSocket::readyRead,[=](){
QByteArray buf = tcpSocket->readAll();
ui->textEdit->append(buf);
});
});
timer = new QTimer;
timer->setSingleShot(true);
connect(timer,&QTimer::timeout,[=](){
sendData();
});
connect(ui->pushButtonOpen,&QPushButton::clicked,[=](){
QString filePath = QFileDialog::getOpenFileName(this,"打开文件","../");
QFileInfo info(filePath);
fileName = info.fileName();
fileSize = info.size();
file.setFileName(filePath);
bool isOpen = file.open(QIODevice::ReadOnly);
if(isOpen == false){
qDebug("源文件打开失败");
return ;
}
ui->textEdit->append(QString("%1 该文件已选中").arg(filePath));
ui->pushButtonSend->setEnabled(true);
ui->pushButtonOpen->setEnabled(false);
});
connect(ui->pushButtonSend,&QPushButton::clicked,[=](){
//先写文件信息
qint64 len = tcpSocket->write(QString(fileName+"##"+QString::number(fileSize)).toLatin1().data());
if(len > 0){
timer->start(100);
}
});
}
serverWidget::~serverWidget()
{
delete ui;
}
void serverWidget::sendData()
{
ui->textEdit->append("开始传送文件。。。。。");
char buf[4*1024]={0};
qint64 readLen = 0;
qint64 writeLen = 0;
qint64 totalLen = 0;
while((readLen = file.read(buf,sizeof (buf))) > 0){
writeLen = tcpSocket->write(buf,readLen);
totalLen += writeLen;
qDebug()<<"readLen="+QString::number(readLen);
}
if(totalLen == fileSize){
ui->textEdit->append("服务器文件发送完毕。。。。");
}else{
ui->textEdit->append("服务器文件发送失败xxxxxx");
}
}
3.客户端的.h文件
#ifndef CLIENTWIDGET_H
#define CLIENTWIDGET_H
#include <QWidget>
#include <QTcpSocket>
#include <QFile>
namespace Ui {
class clientWidget;
}
class clientWidget : public QWidget
{
Q_OBJECT
public:
explicit clientWidget(QWidget *parent = nullptr);
~clientWidget();
private:
Ui::clientWidget *ui;
QTcpSocket *tcpSocket;
bool isStart;
QFile file;
qint16 recvSize;
qint16 fileSize;
};
#endif // CLIENTWIDGET_H
4.客户端的.cpp文件
#include "clientwidget.h"
#include "ui_clientwidget.h"
#include <QHostAddress>
clientWidget::clientWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::clientWidget)
{
ui->setupUi(this);
tcpSocket = new QTcpSocket(this);
setWindowTitle("客户端");
isStart = false;
recvSize = 0;
connect(ui->connectBtn,&QPushButton::clicked,[=](){
tcpSocket->connectToHost(ui->lineEditIP->text(),ui->lineEditPort->text().toUInt());
connect(tcpSocket,&QTcpSocket::readyRead,[=](){
QByteArray buf = tcpSocket->readAll();
if(isStart == false){
isStart = true;
QString fileName = QString(buf).section("##",0,0);
fileSize = QString(buf).section("##",1,1).toInt();
//file = new QFile(QString("C:/Users/Administrator/Desktop/%1").arg(fileName));
file.setFileName(QString("C:/Users/Administrator/Desktop/%1").arg(fileName));
bool isOpen = file.open(QIODevice::WriteOnly);
if(isOpen){
ui->progressBar->setValue(0);
ui->progressBar->setMinimum(0);
ui->progressBar->setMaximum(fileSize/1024);
}else{
file.close();
}
}else{
qint16 len = file.write(buf);
recvSize += len;
ui->progressBar->setValue(recvSize/1024);
if(recvSize == fileSize){
tcpSocket->write("file done");
file.close();
}
}
});
});
connect(ui->disconnectBtn,&QPushButton::clicked,[=](){
tcpSocket->write(QString("%1:%2 disconnect").arg(tcpSocket->localAddress().toString()).arg(tcpSocket->localPort()).toLatin1().data());
tcpSocket->disconnectFromHost();
tcpSocket->close();
});
}
clientWidget::~clientWidget()
{
delete ui;
}
心得:
1.程序异常导致终端错误:【原因1:定义的指针没有new】
2.QFIleDialog | QFileInfo | QFile 等,可以直接使用它的静态公用成员【Static Public Members】。
3.file.close() 与 delete