Client批量向Server发送文件
一,基础定义
QTcpSocket需要在pro文件中添加QT+=network;头文件需要添加
#include <QTcpServer>
#include <QTcpSocket>
#include <QAbstractSocket>
#include <QFile>
定义变量
Server中:
QTcpServer MyTcpServer;
QTcpSocket *tcpServerConnection;
qint64 totalBytes; //存放总大小信息
qint64 bytesReceived; //已收到的数据大小
qint64 fileNameSize; //文件名的大小信息;
QString fileName; //存放文件名
QFile *localFile; //本地文件
QByteArray inBlock; //数据缓冲区,
Client中:
QStringList namelist; //文件路径集合
QFile *localFile; //发送的文件
QTcpSocket *MySocket;
QString fileName; //文件路径
qint64 bytesWritten; //已发送的数据大小
qint64 totalBytes; //选择文件的总大小
qint64 bytesToWrite; //剩余数据大小
qint64 payloadSize; //每次发送数据大小
QByteArray outBlock; //数据缓冲区,
Client.cpp中
payloadSize = 64*1024; //一次发送64k
sendtime = 0;
totalBytes = 0; //选择文件的总大小
bytesWritten = 0; //已发送的数据大小
二,实现思路
1,Client
1,通过Server监听Client的连接。
2,连接成功后Client会触发connected()信号,在该信号槽中选择文件目录。
3,通过遍历解析出文件目录中的文件并发送文件信息给Server。
4,最后发送文件数据给Server.
2,Server
1,Server中监听newConnection()信号,有新连接时触发,在槽中创建套接字用于Client通信。
2,监听readyRead()信号,当内存中有数据就会触发,实现文件数据的接收。
3,监听error(QAbstractSocket::SocketError)信号,连接出错时触发,用于断开连接时。
3,注意
1,Client的发送与Server接收次数是不相同的,并不是发送一次接收就会有一次,。
2,发送文件大小最多一次发送64kb。
三,实现过程
1,使用getExistingDirectory()获取文件目录路径。
QString filename = QFileDialog::getExistingDirectory(this, tr("Open Directory"), "./",
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
2,解析目录中文件名
QDir dir(filename);
QFileInfoList f_list=dir.entryInfoList();
dir.setFilter(QDir::Files|QDir::NoDot|QDir::NoDotAndDotDot|QDir::NoSymLinks);
for(int i=0;i<f_list.count();i++){
QFileInfo f_info=f_list.at(i);
QString stt=f_info.fileName();
QString newfilename=filename+"/"+stt;
QFileInfo fileinfo(newfilename); //新路径
if(stt != "."&&stt !=".."){
if(fileinfo.isFile()==false){//目录
File(newfilename); //循环
}else{//filename
<<newfilename+"/"+stt;
name<<newfilename;
}
}
}
3,发送文件头信息
触发connected()信号,执行
i=sendtime
localFile = new QFile(name[i]);
if(!localFile->open(QFile::ReadOnly)){//只读形式打开文件失败
qDebug()<<"client:open file error";
return;
}
//获取文件大小
totalBytes = localFile->size();
QDataStream sendOut(&outBlock,QIODevice::WriteOnly);
QString currentFileName = name[i].right(name[i].size()
- name[i].lastIndexOf('/')-1);
sendOut << qint64(0) << qint64(0) << currentFileName;
totalBytes += outBlock.size();
sendOut.device()->seek(0);
//返回outBolock的开始,用实际大小信息代替两个qint64(0)空间
sendOut << totalBytes << qint64((outBlock.size() - sizeof(qint64)*2));
//发送完文件头结构后剩余数据大小
bytesToWrite = totalBytes - MySocket->write(outBlock); //剩余数据大小
4,发送文件数据信息
触发bytesWritten(qint64)信号
//已发送文件大小
bytesWritten += numBytes;
if(bytesToWrite > 0){
//每次发送payloadSize 大小的数据 ,64k ,小于64就发送剩余大小
outBlock = localFile->read(qMin(bytesToWrite,payloadSize));//读取本地文件
//qDebug()<<"发送的数据:"<<outBlock;
//计算剩余文件数据大小
bytesToWrite -= MySocket->write(outBlock);
//MySocket->waitForBytesWritten(); //等待数据内容发送
//清空缓冲区
outBlock.resize(0);
}else{
localFile->close();//关闭文件
}
ui->clientProgressBar->setMaximum(totalBytes);
ui->clientProgressBar->setValue(bytesWritten);
if(bytesWritten == totalBytes){
if(sendtime < name.size()-1){
ui->clientStatusLabel->setText(tr("传送文件 %1 成功!").arg(fileName));
totalBytes = 0;
bytesWritten = 0;
localFile->close();
sendtime++; //文件向下遍历
sleep(1000);//等待文件信息发送完毕
//myTimer->start(1000*10);
startTransfer();//发送下一个文件头信息
}
}
void sleep(int i)
{
for(int j=0;j<i*i;j++){
for(int n=0;n<i;n++){
}
}
}
5,监听连接
if(!MyTcpServer.listen(QHostAddress::AnyIPv4,6666))
{
qDebug()<<MyTcpServer.errorString();
close();
return;
}
totalBytes = 0; //初始化数据
bytesReceived = 0;
fileNameSize = 0;
新连接创建套接字,监听readyRead()信号
tcpServerConnection = MyTcpServer.nextPendingConnection();
connect(tcpServerConnection,SIGNAL(readyRead()),this,SLOT(updateServerProgress()));
connect(tcpServerConnection,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(displayError(QAbstractSocket::SocketError)));
6,接收文件头,文件数据
QDataStream in(tcpServerConnection);
if(bytesReceived <= sizeof (qint64)*2){
if((tcpServerConnection->bytesAvailable()>=sizeof (qint64)*2)&&(fileNameSize ==0))
{
in>>totalBytes>>fileNameSize;
bytesReceived += sizeof (qint64) * 2;
}
if((tcpServerConnection->bytesAvailable() >= fileNameSize)&&(fileNameSize != 0)){
//接收文件名并建立文件
in>>fileName;
bytesReceived += fileNameSize;
localFile = new QFile("file/"+fileName);
if(!localFile->open(QFile::WriteOnly)){//写权限
qDebug()<<"server:open file error";
return;
}
}else{
return;
}
}
//接收数据大小小于总数据,写入文件
if(bytesReceived<totalBytes){
bytesReceived += tcpServerConnection->bytesAvailable();
inBlock = tcpServerConnection->readAll();
localFile->write(inBlock);
inBlock.resize(0);
}
ui->serverProgressBar->setMaximum(totalBytes);
ui->serverProgressBar->setValue(bytesReceived);
//文件接收完成时
if(bytesReceived == totalBytes){
totalBytes = 0;//文件总大小
bytesReceived=0;//接收文件大小
fileNameSize = 0;//文件大小置为0
//tcpServerConnection->close(); //关掉套接字
localFile->close();
}
7,Server,Client连接错误或断开连接处理
void MyServer::displayError(QAbstractSocket::SocketError socketError)
{
qDebug()<<"server error:"<<tcpServerConnection->errorString();
tcpServerConnection->close();
ui->serverProgressBar->reset();
ui->serverStatusLabel->setText(tr("服务器就绪"));
}
---------------------------------------------------------------------------END--------------------------------------------------------------------------