阅读量:2
Client 界面:
Server 界面:
Server 操作:
输入端口号后,点击启动监听
Client 操作:
1.连接服务器
输入IP(服务器的IP地址)和端口号后,点击连接按钮,连接成功如下图所示:
2.向服务器发送文件
2.1 点击“选择本地文件”按钮,选择一个本地的文件。
2.2 点击“选择存储在服务器的目录”,选择发送的文件将要存储在服务器的哪个目录中。(此功能可直接在一台电脑上测试,当多台电脑的时候可以将目录改为服务器的实际目录地址)
2.3 点击“发送文件”按钮,即可开始向服务器传输文件,传输成功后客户端会有提示框。
3.下载服务器的文件(服务器向客户端发送文件)
3.1 点击“选择要下载的文件”按钮,选择想要下载的服务器下的文件(此功能可直接在一台电脑上测试,当多台电脑的时候可以将目录改为服务器的实际文件地址)。
3.2 点击“选择下载目录”按钮,选择下载文件的存储位置。
3.3 点击“下载文件”按钮,即可开始下载服务器的文件,下载成功后客户端会有提示框。
Server-Mainwindow核心代码
//设置进度条 ui->progressBar->setRange(0,100); ui->progressBar->setValue(0); QWidget *progressWidget = new QWidget(this); progressWidget->setLayout(new QHBoxLayout()); progressWidget->layout()->addWidget(ui->progressBar); // 创建 QStatusBar // 将小部件添加到 QStatusBar ui->statusbar->addPermanentWidget(progressWidget); // 设置主窗口的状态栏 setStatusBar(ui->statusbar); ui->statusbar->setSizeGripEnabled(false); //创建线程对象 QThread *thread = new QThread; //创建任务对象 RecvFile *recvWork = new RecvFile; //将任务对象移到子线程中 recvWork->moveToThread(thread); connect(this,&MainWindow::startListen,recvWork,&RecvFile::startListen); //更新进度条 connect(recvWork,&RecvFile::curPercent,ui->progressBar,&QProgressBar::setValue); //启动线程 thread->start();
Server-receiver.cpp核心代码
void RecvFile::startListen(unsigned short port) { qDebug()<<port; //分配内存空间 tcpServer = new QTcpServer(this); tcpServer->listen(QHostAddress::Any,port); connect(tcpServer,&QTcpServer::newConnection,[=]() { //取出建立好连接的套接字 tcpSocket = tcpServer->nextPendingConnection(); isStart = true; connect(tcpSocket,&QTcpSocket::readyRead,this,&RecvFile::recvFile); connect(tcpSocket,&QTcpSocket::disconnected,this,[=]() { //断开连接 tcpSocket->close(); tcpSocket->deleteLater(); }); }); } void RecvFile:: recvFile() { qDebug()<<"触发recvFile"; //取出接收的内容 QByteArray buf = tcpSocket->readAll(); if(true == isStart)//之前未接收文件的头部信息 { //接收头部 qDebug()<<"接收头部==="; isStart = false; //解析头部 buf的内容格式 <文件名>##<文件大小> QString token=QString(buf).section("##",0,0);//token qDebug()<<"token1="<<token; recvfilesize = 0;//初始化已接收的文件长度为0 if(token=="197%*FILE*%197"){//是文件 qDebug()<<"文件"; filename = QString(buf).section("##",1,1);//文件名 filesize = QString(buf).section("##",2,2).toUInt();//文件大小 targetDir=QString(buf).section("##",3,3);//文件应存储的目录 qDebug()<<"filename="<<filename; qDebug()<<"filesize="<<filesize; qDebug()<<"targetDir="<<targetDir; } else if(token=="197%*DOWNLOAD*%197"){//请求下载文件信号 qDebug()<<"下载文件请求"; filePath = QString(buf).section("##",1,1);//文件完整路径 storagePath = QString(buf).section("##",2,2);//文件完整路径 qDebug()<<"filePath="<<filePath; qDebug()<<"storagePath="<<storagePath; isStart = true;//信号只是个头,不应该继续接收尾部 sendDownloadFile(filePath,storagePath); return; } else if(token=="197%*CLIENT_RECEIVED*%197"){ qDebug()<<"客户端已成功接收文件"; isStart = true;//信号只是个头,不应该继续接收尾部 return; } else{ qDebug()<<"无效token!"; return; } filename=targetDir+"\\"+filename;//设置文件位置 file.setFileName(filename); qDebug()<<"filename="<<filename; bool isOk = file.open(QIODevice::WriteOnly); if(false == isOk)//打开失败 { return; } } else//文件的头部信息已经接收 { qDebug()<<"接收尾部==="; qint64 len = file.write(buf);//将buf中的数据写入file文件,并返回实际写入的字节数。 if(len>0) { recvfilesize += len;//累计接收大小 int percent = ((recvfilesize)*100)/filesize; //发出更新进度条的信号 //qDebug()<<"percent="<<percent; emit curPercent(percent); } if(recvfilesize == filesize) { //emit recvOver();//接收完毕 qDebug()<<"接收完毕1"; file.close(); isStart = true; //通知客户端 接收完毕 // 文件传输成功后发送文件接收完毕的信息给客户端 //============================================Token================================================================== QString token="197%*SERVER_RECEIVED*%197"; //============================================Token================================================================== QByteArray completionMessage = token.toUtf8(); completionMessage.append("##"); tcpSocket->write(completionMessage); tcpSocket->waitForBytesWritten(); // 等待数据写入完毕 } else{ qDebug()<<"recvfilesize != filesize"; //isStart = true; } } } void RecvFile::sendDownloadFile(QString path,QString targetDir)//发送头 { timer = new QTimer(this); connect(timer,&QTimer::timeout,[=]() { //关闭定时器 timer->stop(); //发送文件数据 sendDownloadFileData(); }); file.setFileName(path); //获取文件信息 QFileInfo info(path); filesize = info.size();//获取文件大小 filename = info.fileName();//获取文件名 //============================================Token================================================================== QString token="197%*FILE*%197"; //============================================Token================================================================== //只读方式打开文件 bool isOk = file.open(QIODevice::ReadOnly); if(true == isOk) { //创建文件头信息 QString head = QString("%1##%2##%3##%4").arg(token).arg(filename).arg(filesize).arg(targetDir); //创建文件头信息,格式为"文件名##文件大小",例如 "example.txt##1024" //发送头部信息 qint64 len = tcpSocket->write(head.toUtf8()); if(len>0)//发送成功 { //防止tcp黏包问题,延时20ms timer->start(20); } else { //发送失败 file.close(); } } else { QMessageBox::warning(nullptr,"错位","打开文件失败!"); return; } }