文件传输流程:
服务器端:
serverwidget.ui
serverwidget.h
#ifndef SERVERWIDGET_H
#define SERVERWIDGET_H#include <QWidget>
#include<QTcpServer>//监听套接字
#include<QTcpSocket>//通信套接字
#include<QFile>
#include<QTimer>QT_BEGIN_NAMESPACE
namespace Ui { class ServerWidget; }
QT_END_NAMESPACEclass ServerWidget : public QWidget
{Q_OBJECTpublic:ServerWidget(QWidget *parent = nullptr);~ServerWidget();void sendData();//发送文件数据private slots:void on_buttonFile_clicked();void on_buttonSend_clicked();private:Ui::ServerWidget *ui;QTcpServer *tcpServer;//监听套接字QTcpSocket *tcpSocket;//通信套接字QFile file;//文件对象QString fileName;//文件名字qint64 fileSize;//文件大小qint64 sendSize;//已经发送文件大小QTimer timer;//定时器};
#endif // SERVERWIDGET_H
serverwidget.cpp
#include "serverwidget.h"
#include "ui_serverwidget.h"
#include<QFileDialog>
#include<QDebug>
#include<QFileInfo>
#include<QTimer>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->buttonFile->setEnabled(false);ui->buttonSend->setEnabled(false);//如果客户端成功和服务器连接//tcpServer会自动触发newConnection()connect(tcpServer,&QTcpServer::newConnection,[=](){//取出建立好连接的套接字tcpSocket = tcpServer->nextPendingConnection();//获取对方的IP和端口QString ip = tcpSocket->peerAddress().toString();quint16 port = tcpSocket->peerPort();QString str = QString("[%1:%2] 成功连接").arg(ip).arg(port);ui->textEdit->setText(str);//显示到编辑区//成功连接后,才能选择文件ui->buttonFile->setEnabled(true);});connect(&timer,&QTimer::timeout,[=](){//关闭定时器timer.stop();//发送文件sendData();});}ServerWidget::~ServerWidget()
{delete ui;
}//选择文件按钮
void ServerWidget::on_buttonFile_clicked()
{QString filePath = QFileDialog::getOpenFileName(this,"open","../");if(false == filePath.isEmpty())//如果选择文件路径有效{fileName.clear();fileSize = 0;//获取文件信息QFileInfo info(filePath);fileName = info.fileName();//获取文件名字fileSize = info.size();//获取文件大小sendSize = 0;//发送文件的大小//只读方式打开//指定文件的名字file.setFileName(filePath);//打开文件bool isOK = file.open(QIODevice::ReadOnly);if(false == isOK){qDebug()<<"只读的方式打开文件失败 77";}//提示打开文件的路径ui->buttonFile->setEnabled(false);ui->buttonSend->setEnabled(true);}else{qDebug()<<"选择文件路径出错 62";}}
//发送文件按钮
void ServerWidget::on_buttonSend_clicked()
{//先发送文件头信息QString head = QString("%1##%2").arg(fileName).arg(fileSize);//发送头部信息qint64 len = tcpSocket->write(head.toUtf8());if(len > 0)//头部信息发送成功{//发送真正的文件信息//防止TCP黏包问题//需要通过定时器延时20 mstimer.start(20);}else{qDebug()<<"头部信息发送失败 110";file.close();ui->buttonFile->setEnabled(true);ui->buttonSend->setEnabled(false);}
}void ServerWidget::sendData()
{qint64 len = 0;do{char buf[4*1024] = {0};len = 0;//往文件在读数据len = file.read(buf,sizeof(buf));//发送数据,读多少,发多少len = tcpSocket->write(buf,len);//发送的数据需要积累sendSize += len;}while(len > 0);//是否发送文件完毕if(sendSize == fileSize){ui->textEdit->append("文件发送完毕");file.close();//把客户端挂关闭tcpSocket->disconnectFromHost();tcpSocket->close();}
}
客户端:
main.cpp
#include "serverwidget.h"
#include"clientwidget.h"
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);ServerWidget w;w.show();ClientWidget w2;w2.show();return a.exec();
}
clientwidget.ui
clientwidget.h
#ifndef CLIENTWIDGET_H
#define CLIENTWIDGET_H#include <QWidget>
#include<QTcpSocket>//通信套接字
#include<QFile>namespace Ui {
class ClientWidget;
}class ClientWidget : public QWidget
{Q_OBJECTpublic:explicit ClientWidget(QWidget *parent = nullptr);~ClientWidget();private slots:void on_pushButton_clicked();private:Ui::ClientWidget *ui;QTcpSocket *tcpSocket;//通信套接字QFile file;//文件对象QString fileName;//文件名字qint64 fileSize;//文件大小qint64 recvSize;//已经接收文件大小bool isStart;
};#endif // CLIENTWIDGET_H
clientwidget.cpp
#include "clientwidget.h"
#include "ui_clientwidget.h"
#include<QDebug>
#include<QMessageBox>
#include<QHostAddress>ClientWidget::ClientWidget(QWidget *parent) :QWidget(parent),ui(new Ui::ClientWidget)
{ui->setupUi(this);tcpSocket = new QTcpSocket(this);isStart = true;connect(tcpSocket,&QTcpSocket::readyRead,[=](){//取出接收的内容QByteArray buf = tcpSocket->readAll();if(true == isStart){//接收头isStart = false;//解析头部信息 QString buf = "hello##1024"
// QString str = "hello##1024##mike";
// str.section("##",0,0);//以##进行拆分//初始化fileName = QString(buf).section("##",0,0);fileSize = QString(buf).section("##",1,1).toInt();recvSize = 0;//打开文件file.setFileName(fileName);bool isOK = file.open(QIODevice::WriteOnly);if(false == isOK){qDebug()<<"WriteOnly error 40";}}else//文件信息{qint64 len = file.write(buf);recvSize += len;if(recvSize == fileSize){file.close();QMessageBox::information(this,"完成","文件接收完成");tcpSocket->disconnectFromHost();tcpSocket->close();}}});}ClientWidget::~ClientWidget()
{delete ui;
}void ClientWidget::on_pushButton_clicked()
{//获取服务器的IP和端口QString ip = ui->lineEditIP->text();quint16 port = ui->lineEditPort->text().toInt();tcpSocket->connectToHost(QHostAddress(ip),port);
}
输出如下所示:
在当前目录下可找到传输的文件