您的位置:首页 > 游戏 > 游戏 > qt客户端与服务端关于传输文件

qt客户端与服务端关于传输文件

2024/12/22 22:45:23 来源:https://blog.csdn.net/qq_73937769/article/details/141102211  浏览:    关键词:qt客户端与服务端关于传输文件

如果直接发 发送的数据永远要比接受的块 需要有时间间隔 此时定时器的作用就显现出来了

发送数据都先发头,要保证服务器发送的头,客户端能接受到

发送数据后不要直接读数据,加一个延迟

这里以##作为分隔符

发送多少读多少,

发送数据的操作

QT网络编程中关于发送文件的操作函数  规则就是从文件中读取多少就发送多少
void ServerWidget::senddata()
{qint64 len =0;do{//每次读4k的内容char buf[4*1024] ={0};len =  file.read(buf,sizeof(buf));  //read函数返回值为qint64//读多少发多少len =socket->write(buf,len); //统计的发送数据sendsize+=len;
//累积的文件大小}while(len>0);//判断文件发送完毕和总的文件作比较即可if(sendsize==filesize){//提示用户ui->textEdit->append("文件已发送完毕");file.close();//发送完毕后断开连接 ,以免丢包
//建立好的通讯套接字断开连接socket->disconnectFromHost();socket->close();}
}

这个函数调用前需要有定时器的相关操作

需要先激活定时器 先发送头  间隔20ms发送

void ServerWidget::on_butsend_clicked()
{//发送文件头信息QString head = QString("%1##%2").arg(filename).arg(filesize);qint64 len =    socket->write(head.toUtf8()); // write函数返回值为qint64if(len>0){// qDebug()<<"发送成功";timer->start(20);}else{qDebug()<<"发送信息失败";file.close();ui->butselect->setEnabled(1);ui->butselect->setEnabled(0);}}

在选择按钮的函数中调用connect()关联信号和槽

void ServerWidget::on_butselect_clicked()
{// QString getOpenFileName(QWidget *parent = nullptr, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilterQString path = QFileDialog::getOpenFileName(this,"打开文件","../");if(path.isEmpty()==false){//路径不为空的话就打开该文件//每次选择文件的时候将文件名和大小清空filename.clear();filesize =0;QFileInfo info(path);//QFileInfo中有文件信息的成员函数// file.open();filename = info.fileName(); //获取文件名字filesize = info.size();//获取文件大小//用变量来标记文件发送了多少  防止丢包sendsize =0 ;//指定文件名字,只读方式打开文件按file.setFileName(path);if(!file.open(QIODevice::ReadOnly)){qDebug()<<"只读方式打开文件失败"<<'\n';}//提示用户打开文件的路径ui->textEdit->append(path);ui->butselect->setEnabled(false);ui->butselect->setEnabled(true);}else{qDebug()<<"选择文件无效"<<'\n';}connect(timer,&QTimer::timeout,[=](){timer->stop();senddata();});
}

客户端:

#include "clientwidget.h"
#include "ui_clientwidget.h"
#include <QMessageBox>
#include <QHostAddress>
Clientwidget::Clientwidget(QWidget *parent): QWidget(parent), ui(new Ui::Clientwidget)
{ui->setupUi(this);setWindowTitle("客户端");//ui->progressBar->setValue(0);//设置进度条的值isstart = true;csocket = new QTcpSocket(this);connect(csocket,&QTcpSocket::readyRead,[=](){QByteArray buf = csocket->readAll();if(true==isstart){isstart = false;//初始化filename = QString(buf).section("##",0,0);filesize = QString(buf).section("##",1,1).toInt();recivesize =0;//打开文件file.setFileName(filename);bool isok = file.open(QIODevice::WriteOnly);if(false ==isok){qDebug()<<"write only errno 29";}QString str = QString("接受的文件:[%1:%2kb]").arg(filename).arg(filesize/1024);QMessageBox::information(this,"文件信息",str);ui->progressBar->setMinimum(0);ui->progressBar->setMaximum(100);ui->progressBar->setValue(0);}else{qint64 len = file.write(buf);if(len>0){recivesize+=len;QString str = QString::number(recivesize);csocket->write(str.toUtf8().data());//qDebug()<<len;}ui->progressBar->setValue(recivesize/1024);if(recivesize==filesize){csocket->write("file done");QMessageBox::information(this,"提示","文件接受完成");file.close();csocket->disconnectFromHost();csocket->close();return ;}}});/*
String::section() 是 Qt 中 QString 类的一个成员函数,用于从字符串中提取指定范围内的子字符串。它可以根据分隔符或索引位置来提取子字符串。QString::section() 函数签名
QString section(QChar sep, int startIndex, int endIndex, QString::SectionFlags flags = KeepEmptyParts) const;参数说明
sep:分隔符,用于分割字符串。
startIndex:起始索引,表示从第几个分隔符开始提取。
endIndex:结束索引,表示到第几个分隔符结束提取。
flags:标志位,控制如何处理空的部分,默认为 KeepEmptyParts。
返回值
返回一个 QString,包含了从 startIndex 到 endIndex 之间的子字符串。*/
}Clientwidget::~Clientwidget()
{delete ui;
}void Clientwidget::on_butconnect_clicked()
{QString ip = ui->ipedit->text();quint64 port = ui->portedit->text().toInt();csocket->connectToHost(QHostAddress(ip),port);
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com