QTcpSocket目录文件传输

一,基础定义

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--------------------------------------------------------------------------

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
Qt中使用QTcpSocket传输文件可以分为两个部分:服务器端和客户端。 服务器端: 1. 创建一个QTcpServer对象并监听客户端连接。 2. 在QTcpServer的newConnection()信号中,获取连接的套接字(QTcpSocket)。 3. 将套接字与文件相关联,以便传输文件。 4. 通过套接字读取文件内容并发送给客户端。 5. 关闭套接字和文件。 客户端: 1. 创建一个QTcpSocket对象并连接到服务器。 2. 发送一个请求,告诉服务器要下载哪个文件。 3. 从套接字读取文件内容并保存到本地文件。 4. 关闭套接字和文件。 下面是一个简单的例子: 服务器端: ```cpp QTcpServer server; server.listen(QHostAddress::Any, 8888); // 监听任意地址的8888端口 connect(&server, &QTcpServer::newConnection, this, [=]() { QTcpSocket *socket = server.nextPendingConnection(); QFile file("path/to/file"); if (file.open(QIODevice::ReadOnly)) { while (!file.atEnd()) { QByteArray buffer = file.read(1024); // 每次读取1024字节 socket->write(buffer); } file.close(); } socket->disconnectFromHost(); }); ``` 客户端: ```cpp QTcpSocket socket; socket.connectToHost(QHostAddress("127.0.0.1"), 8888); // 连接到服务器 if (socket.waitForConnected()) { socket.write("path/to/file"); // 发送请求 QFile file("path/to/save/file"); if (file.open(QIODevice::WriteOnly)) { while (socket.bytesAvailable() > 0) { QByteArray buffer = socket.read(1024); // 每次读取1024字节 file.write(buffer); } file.close(); } socket.disconnectFromHost(); } ``` 需要注意的是,上面的例子只适用于小文件的传输。如果要传输大文件,可以考虑分成多个数据包传输并在客户端进行组装,或者使用Qt的QDataStream来进行数据流的传输。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

撸BUG

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值