├── tcpClient ├── KFileTransferSender.cpp ├── KFileTransferSender.h ├── Singleton.h ├── config.h ├── kfiletransfercachemanage.cpp ├── kfiletransfercachemanage.h ├── main.cpp ├── mainwindow.cpp ├── mainwindow.h ├── mainwindow.ui └── tcpClient.pro └── tcpServer ├── KFileTransferRecevicer.cpp ├── KFileTransferRecevicer.cpp.bak ├── KFileTransferRecevicer.h ├── KFileTransferRecevicer.h.bak ├── Singleton.h ├── config.h ├── kfiletransfercachemanage.cpp ├── kfiletransfercachemanage.h ├── ksqlobject.cpp ├── ksqlobject.h ├── main.cpp ├── mainwindow.cpp ├── mainwindow.h ├── mainwindow.ui └── tcpServer.pro /tcpClient/KFileTransferSender.cpp: -------------------------------------------------------------------------------- 1 | //#include "stdafx.h" 2 | #include "KFileTransferSender.h" 3 | 4 | #ifndef USE_QTCREATOR 5 | #include "KSignalSpy.h" 6 | #else 7 | #include 8 | #endif 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | KFileTransferSender::KFileTransferSender(QObject *parent) 16 | :QObject(parent) 17 | , _bCancel(false) 18 | , _bRunning(false) 19 | , _nextBlockSize(0) 20 | , _recvDataSize(0) 21 | , _timeoutMsec(3000) 22 | , _filesize(0) 23 | , _sendSize(0) 24 | { 25 | _pCommandSocket = new QTcpSocket(this); 26 | _pool.setMaxThreadCount(1); 27 | } 28 | 29 | bool KFileTransferSender::connect_to_server(const QString &ipAddress, int port) 30 | { 31 | m_ipAddress = ipAddress; 32 | _pCommandSocket->connectToHost(QHostAddress(ipAddress), port); 33 | bool ret = _pCommandSocket->waitForConnected(_timeoutMsec); 34 | if (ret) 35 | { 36 | connect(_pCommandSocket,SIGNAL(readyRead()),this,SLOT(on_read_command())); 37 | } 38 | else 39 | { 40 | emit errorState(ERROR_CLASSIFY_EM::K_NETWORK_ERROR, K_NETWORK_ERROR_EM::K_NETWORK_DISCONNECTED_COMMAND_ERROR); 41 | } 42 | return ret; 43 | } 44 | 45 | void KFileTransferSender::sendFile(const QString &filePath) 46 | { 47 | //文件大小为0处理; 48 | QFileInfo filInfo(filePath); 49 | if (0 == filInfo.size()) 50 | { 51 | emit progressValue(filePath, 100); 52 | emit fileTransferFinish(); 53 | } 54 | 55 | if( set_file(filePath)) 56 | { 57 | send_command(FILE_HEAD_CODE); 58 | } 59 | } 60 | 61 | bool KFileTransferSender::cancelSendFile() 62 | { 63 | send_command(FILE_CANCEL); 64 | 65 | #ifndef USE_QTCREATOR 66 | KSignalSpy spy(this, SIGNAL(cancelSendFileRspSig(int, QVariant))); 67 | #else 68 | QSignalSpy spy(this, SIGNAL(cancelSendFileRspSig(int, QVariant))); 69 | #endif // !USE_QTCREATOR 70 | if (spy.wait(_timeoutMsec)) 71 | { 72 | QList arguments = spy.takeFirst(); 73 | if (arguments.at(0).toInt() == FILE_REC_CANCEL) 74 | { 75 | return arguments.at(1).toInt(); 76 | } 77 | } 78 | else 79 | { 80 | emit errorState(ERROR_CLASSIFY_EM::K_RESPONSE_TIMEOUT, K_RESPONSE_TIMEOUT_EM::K_RESPONSE_CANCEL_FILE_TIMEOUT); 81 | return false; 82 | } 83 | return false; 84 | } 85 | 86 | bool KFileTransferSender::isDiskFreeSpace(quint64 reqSpaceSize) 87 | { 88 | send_command(FILE_IS_DISK_FREE_SPACE_CODE, reqSpaceSize); 89 | #ifndef USE_QTCREATOR 90 | KSignalSpy spy(this, SIGNAL(isDiskFreeSpaceRspSig(int, QVariant))); 91 | #else 92 | QSignalSpy spy(this, SIGNAL(isDiskFreeSpaceRspSig(int, QVariant))); 93 | #endif // !USE_QTCREATOR 94 | if (spy.wait(_timeoutMsec)) 95 | { 96 | QList arguments = spy.takeFirst(); 97 | if (arguments.at(0).toInt() == FILE_IS_DISK_FREE_SPACE_REC_CODE) 98 | { 99 | return arguments.at(1).toInt(); 100 | } 101 | } 102 | else 103 | { 104 | emit errorState(ERROR_CLASSIFY_EM::K_RESPONSE_TIMEOUT, K_RESPONSE_TIMEOUT_EM::K_RESPONSE_IS_DISK_FREE_SPACE_FILE_TIMEOUT); 105 | return false; 106 | } 107 | return false; 108 | } 109 | 110 | void KFileTransferSender::isExistFile(QList& fileStruList) 111 | { 112 | for (checkfileStru &fileStru : fileStruList) 113 | { 114 | if(fileStru.filePath.isEmpty()) 115 | { 116 | qDebug()<< __FUNCTION__ << fileStru.filePath << ERROR_CODE_1; 117 | } 118 | else 119 | { 120 | QFileInfo info(fileStru.filePath); 121 | //QString fileName = info.absoluteFilePath(); 122 | //qint64 fileSize = info.size(); 123 | 124 | send_command(FILE_IS_EXIST_CODE, fileStru.filePath + SPLIT_ADDITION_INFO_MARK + QString::number(fileStru.fileSize) + SPLIT_ADDITION_INFO_MARK + fileStru.md5Str); 125 | #ifndef USE_QTCREATOR 126 | KSignalSpy spy(this, SIGNAL(isExistFileRspSig(int, QVariant))); 127 | #else 128 | QSignalSpy spy(this, SIGNAL(isExistFileRspSig(int, QVariant))); 129 | #endif // !USE_QTCREATOR 130 | if (spy.wait(_timeoutMsec)) 131 | { 132 | QList arguments = spy.takeFirst(); 133 | if (arguments.at(0).toInt() == FILE_IS_EXIST_REC_CODE) 134 | { 135 | fileStru.bExist = arguments.at(1).toInt(); 136 | } 137 | } 138 | else 139 | { 140 | emit errorState(ERROR_CLASSIFY_EM::K_RESPONSE_TIMEOUT, K_RESPONSE_TIMEOUT_EM::K_RESPONSE_IS_EXIST_FILE_TIMEOUT); 141 | } 142 | } 143 | } 144 | } 145 | 146 | bool KFileTransferSender::set_file(const QString &filePath) 147 | { 148 | if(filePath.isEmpty()) 149 | { 150 | qDebug()<< ERROR_CODE_1; 151 | return false; 152 | } 153 | QFileInfo info(filePath); 154 | _filename = info.absoluteFilePath(); 155 | _filesize = info.size(); 156 | _sendSize = 0; 157 | 158 | if(_file.isOpen()) 159 | { 160 | _file.close(); 161 | } 162 | _file.setFileName(filePath); 163 | bool isOk = _file.open(QIODevice::ReadOnly); 164 | if(false == isOk) 165 | { 166 | qDebug()<write(command.toUtf8()); 209 | _pCommandSocket->waitForBytesWritten(-1); 210 | if(len <= 0) 211 | { 212 | qDebug()<< "命令代号:" << type << ERROR_CODE_3; 213 | _file.close(); 214 | return false; 215 | } 216 | return true; 217 | } 218 | 219 | void KFileTransferSender::send_file() 220 | { 221 | qint64 len = 0; 222 | QTcpSocket file_socket; 223 | file_socket.connectToHost(QHostAddress(m_ipAddress), PORT_FILE); 224 | bool ret = file_socket.waitForConnected(_timeoutMsec); 225 | if (ret) 226 | { 227 | connect(&file_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onFileError(QAbstractSocket::SocketError))/*, Qt::QueuedConnection*/); 228 | } 229 | else 230 | { 231 | emit errorState(ERROR_CLASSIFY_EM::K_NETWORK_ERROR, K_NETWORK_ERROR_EM::K_NETWORK_DISCONNECTED_FILE_ERROR); 232 | } 233 | 234 | 235 | if (! _file.isOpen()) 236 | { 237 | bool bOk = _file.open(QIODevice::ReadOnly); 238 | if (bOk) 239 | { 240 | qDebug() << "开始发送文件数据信息 " << QDateTime::currentDateTime().toString("YYYY-MM-DD HH:mm:ss:zzz"); 241 | } 242 | else 243 | { 244 | qDebug()<发送的数据数据大小:" << len / 1024 << "KB" << "\t已发送数据大小:" << _sendSize / 1024 << "KB"; 264 | } while(len > 0); 265 | 266 | if(_sendSize == _filesize) 267 | { 268 | _sendSize = 0; 269 | _file.close(); 270 | file_socket.disconnect(); 271 | file_socket.close(); 272 | 273 | qDebug() << "文件 " << _file.fileName() << "发送完毕 " 274 | << QDateTime::currentDateTime().toString("YYYY-MM-DD HH:mm:ss:zzz"); 275 | } 276 | _bRunning = false; 277 | } 278 | 279 | void KFileTransferSender::on_read_command() 280 | { 281 | QDataStream out(_pCommandSocket); 282 | out.setVersion(QDataStream::Qt_5_9); 283 | if (_nextBlockSize == 0) 284 | { 285 | if (_pCommandSocket->bytesAvailable() >= sizeof(qint64)) 286 | { 287 | out >> _nextBlockSize; 288 | } 289 | } 290 | 291 | if (_pCommandSocket->bytesAvailable() >= _nextBlockSize) 292 | { 293 | QByteArray array; 294 | out >> array; 295 | _cacheData = QString(array); 296 | //out >> _cacheData; 297 | dealReadCommand(); 298 | _cacheData.clear(); 299 | _nextBlockSize = 0; 300 | } 301 | } 302 | 303 | void KFileTransferSender::onCommandError(QAbstractSocket::SocketError socketError) 304 | { 305 | qDebug() << __FUNCTION__ << _pCommandSocket->errorString(); 306 | } 307 | 308 | void KFileTransferSender::onFileError(QAbstractSocket::SocketError socketError) 309 | { 310 | qDebug() << __FUNCTION__ << socketError; 311 | //quitFileTransferThread(); 312 | } 313 | 314 | void KFileTransferSender::dealReadCommand() 315 | { 316 | int code = _cacheData.section(SPLIT_TYPE_INFO_MAEK,0,0).toInt(); 317 | int ret = _cacheData.section(SPLIT_TYPE_INFO_MAEK,1,1).toInt(); 318 | QString additionalInfo = _cacheData.section(SPLIT_TYPE_INFO_MAEK,2,2); 319 | switch(code) 320 | { 321 | //发送文件头响应处理 322 | case FILE_HEAD_REC_CODE: 323 | { 324 | #ifdef USE_THREAD_TRANSFER 325 | if(ret) 326 | { 327 | quitFileTransferThread(); 328 | _fileTransferFuture = QtConcurrent::run(&_pool, [this] { send_file(); }); 329 | _bRunning = true; 330 | 331 | _cancelFileTransferMutex.lock(); 332 | _bCancel = false; 333 | _cancelFileTransferMutex.unlock(); 334 | } 335 | else 336 | { 337 | qDebug() << ERROR_CODE_4; 338 | } 339 | #else 340 | if(ret) 341 | { 342 | send_file(); 343 | } 344 | else 345 | { 346 | qDebug() << ERROR_CODE_4; 347 | } 348 | #endif 349 | break; 350 | } 351 | //接收文件数据完成响应处理 352 | case FILE_REC_CODE: 353 | { 354 | if(ret) 355 | { 356 | bool ok; 357 | qint64 recv = additionalInfo.toLongLong(&ok, 10); 358 | if (_filesize > 0) 359 | { 360 | int progressVal = (recv * 100) / _filesize; 361 | emit progressValue(_filename, progressVal); 362 | } 363 | 364 | qDebug() << "文件大小:" << _filesize << "KB,\t已接收数据大小:" << recv << "KB"; 365 | } 366 | else 367 | { 368 | qDebug() << ERROR_CODE_5; 369 | } 370 | break; 371 | } 372 | //取消文件传输响应处理 373 | case FILE_REC_CANCEL: 374 | { 375 | _cancelFileTransferMutex.lock(); 376 | _bCancel = true; 377 | _cancelFileTransferMutex.unlock(); 378 | _sendSize = 0; 379 | if (_file.isOpen()) 380 | { 381 | _file.close(); 382 | } 383 | emit progressValue(_filename, 0); 384 | emit cancelSendFileRspSig(code, QVariant(ret)); 385 | break; 386 | } 387 | //检查查询的文件是否存在响应处理 388 | case FILE_IS_EXIST_REC_CODE: 389 | { 390 | emit isExistFileRspSig(code, QVariant(ret)); 391 | break; 392 | } 393 | //判断添加文件后是否会空间不足响应处理 394 | case FILE_IS_DISK_FREE_SPACE_REC_CODE: 395 | { 396 | emit isDiskFreeSpaceRspSig(code, QVariant(ret)); 397 | break; 398 | } 399 | //文件传输超时,服务端主动通知客户端; 400 | case FILE_TRANSFER_TIMEOUT_CODE: 401 | { 402 | errorState(ERROR_CLASSIFY_EM::K_RESPONSE_TIMEOUT, K_RESPONSE_TIMEOUT_EM::K_RESPONSE_FILE_TRANSFER_TIMEOUT); 403 | break; 404 | } 405 | case FILE_TRANSFER_FINISH_CODE: 406 | { 407 | emit fileTransferFinish(); 408 | qDebug() << __FUNCTION__ << _filename << "文件传输完成"; 409 | break; 410 | } 411 | default: 412 | qDebug() << __FUNCTION__ << ":read command error."; 413 | break; 414 | } 415 | } 416 | 417 | void KFileTransferSender::quitFileTransferThread() 418 | { 419 | while (_bRunning) 420 | { 421 | _cancelFileTransferMutex.lock(); 422 | _bCancel = true; 423 | _cancelFileTransferMutex.unlock(); 424 | QThread::msleep(10); 425 | } 426 | } 427 | -------------------------------------------------------------------------------- /tcpClient/KFileTransferSender.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "config.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | class KFileTransferSender:public QObject 15 | { 16 | Q_OBJECT 17 | public: 18 | explicit KFileTransferSender(QObject *parent = nullptr); 19 | bool connect_to_server(const QString &ipAddress, int port); //连接至服务器 20 | void sendFile(const QString &filePath); //发送文件 21 | bool cancelSendFile(); //取消文件 22 | void isExistFile(QList& fileStruList); //检查文件是否存在 23 | bool isDiskFreeSpace(quint64 reqSpaceSize); //检查磁盘空间是否不足 24 | signals: 25 | void progressValue(const QString &fileName, int progressVal); //服务端已接受的数据进度 26 | void fileTransferFinish(); //文件传输完成信号 27 | void errorState(int code, int subCode); //错误状态 28 | 29 | void isExistFileRspSig(int type, QVariant retValue); //查询文件是否存在响应信号 30 | void isDiskFreeSpaceRspSig(int type, QVariant retValue); //查询磁盘空间是否不足响应信号 31 | void cancelSendFileRspSig(int type, QVariant retValue); //取消文件传输响应信号 32 | private slots: 33 | void on_read_command(); //响应服务端信息 34 | void onCommandError(QAbstractSocket::SocketError); //命令socket错误 35 | void onFileError(QAbstractSocket::SocketError); //文件socket错误 36 | private: 37 | void send_file(); //发送文件内容数据 38 | bool send_command(int type, QVariant additionalInfo = ""); //发送文件信息命令 39 | bool set_file(const QString& filePath); //设置文件 40 | void dealReadCommand(); 41 | void quitFileTransferThread(); //退出文件传输线程 42 | 43 | private: 44 | QTcpSocket *_pCommandSocket; 45 | 46 | QFile _file; 47 | QString _filename; 48 | qint64 _filesize; 49 | qint64 _sendSize; 50 | QString _serverip; 51 | QThreadPool _pool; 52 | QFuture _fileTransferFuture; 53 | QMutex _cancelFileTransferMutex; 54 | bool _bCancel; 55 | bool _bRunning; 56 | qint64 _nextBlockSize; //下一块大小 57 | qint64 _recvDataSize; //已接收数据大小 58 | QString _cacheData; //缓存数据容器 59 | 60 | int _timeoutMsec; //超时时间 61 | QString m_ipAddress; 62 | }; 63 | -------------------------------------------------------------------------------- /tcpClient/Singleton.h: -------------------------------------------------------------------------------- 1 | #ifndef _KOMMANDER_TOOL_SINGLETON_H_ 2 | #define _KOMMANDER_TOOL_SINGLETON_H_ 3 | 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | //#include 9 | 10 | //typedef std::function DelSingletonAction; 11 | //typedef QQueue SingletonDeleteQueue; 12 | 13 | //void pushSingletonAction(DelSingletonAction delAction); 14 | //void clearSingleton(); 15 | 16 | template 17 | class KSingleton 18 | { 19 | public: 20 | template 21 | static T* instance(Args&&... args) 22 | { 23 | static T* _instance = nullptr; 24 | static std::once_flag oc; 25 | std::call_once(oc, [&] { 26 | _instance = new T(std::forward(args)...); 27 | }); 28 | return _instance; 29 | } 30 | 31 | private: 32 | KSingleton() {} 33 | virtual ~KSingleton() {} 34 | KSingleton(const KSingleton& st) {} 35 | KSingleton &operator=(const KSingleton& st) {} 36 | }; 37 | 38 | #define SINGLETON(x,...) KSingleton::instance(__VA_ARGS__) 39 | #define SINGLETONDELETE(x) { delete SINGLETON(x); } 40 | #define DECLARESINGLETON(clsname) friend class KSingleton; 41 | #define CLEARSINGLETON { clearSingleton(); } 42 | #endif 43 | 44 | 45 | -------------------------------------------------------------------------------- /tcpClient/config.h: -------------------------------------------------------------------------------- 1 | #ifndef CONFIG_H 2 | #define CONFIG_H 3 | 4 | #include 5 | 6 | #define IP "127.0.0.1" 7 | //#define IP "192.168.0.120" 8 | #define PORT_COMMAND 8888 9 | #define PORT_FILE 8848 10 | 11 | #define USE_THREAD_TRANSFER 12 | #define USE_QTCREATOR 13 | 14 | #define SEND_BLOCK_SIZE (qint64)(4 * 1024 * 1024) 15 | 16 | #define SPLIT_TYPE_INFO_MAEK "##" 17 | #define SPLIT_ADDITION_INFO_MARK ",," 18 | 19 | #define K_ERROR false 20 | #define K_SUCCEED true 21 | 22 | #define ERROR_CODE_1 "设置的文件路径错误" 23 | #define ERROR_CODE_2 "要上传的文件打开失败" 24 | #define ERROR_CODE_3 "命令发送失败" 25 | #define ERROR_CODE_4 "文件头部信息接收失败" 26 | #define ERROR_CODE_5 "文件数据接收失败" 27 | #define ERROR_CODE_6 "磁盘空间已不足,无法存储该文件" 28 | #define ERROR_CODE_7 "不能再次点击取消操作" 29 | #define ERROR_CODE_8 "查询文件是否存在,附加信息错误" 30 | #define ERROR_CODE_9 "设置的缓存目录错误" 31 | #define ERROR_CODE_10 "文件在缓存中不存在" 32 | #define ERROR_CODE_11 "文件传输超时" 33 | 34 | #define SUCCEED_CODE_1 "文件头部信息接收成功" 35 | #define SUCCEED_CODE_2 "接收端文件数据接收完成" 36 | #define SUCCEED_CODE_3 "接收端文件取消完成" 37 | #define SUCCEED_CODE_4 "文件在缓存中存在" 38 | #define SUCCEED_CODE_5 "磁盘空间大小足够存储该文件" 39 | 40 | //错误分类 41 | enum ERROR_CLASSIFY_EM 42 | { 43 | K_FILE_TRANSFER_ERROR = 100, 44 | K_NETWORK_ERROR = K_FILE_TRANSFER_ERROR + 200, 45 | K_RESPONSE_TIMEOUT = K_NETWORK_ERROR + 200 46 | }; 47 | 48 | //文件传输错误 49 | enum K_FILE_TRANSFER_ERROR_EM 50 | { 51 | K_FILE_TRANSFER_CANCEL_ERROR = ERROR_CLASSIFY_EM::K_FILE_TRANSFER_ERROR + 1 //传输取消错误 52 | }; 53 | 54 | //网络错误 55 | enum K_NETWORK_ERROR_EM 56 | { 57 | K_NETWORK_DISCONNECTED_COMMAND_ERROR = ERROR_CLASSIFY_EM::K_NETWORK_ERROR + 1, //网络连接命令socket错误 58 | K_NETWORK_DISCONNECTED_FILE_ERROR //网络连接文件socket错误 59 | }; 60 | 61 | enum K_RESPONSE_TIMEOUT_EM 62 | { 63 | K_RESPONSE_CANCEL_FILE_TIMEOUT = ERROR_CLASSIFY_EM::K_RESPONSE_TIMEOUT + 1, //取消文件超时 64 | K_RESPONSE_IS_DISK_FREE_SPACE_FILE_TIMEOUT, //判断磁盘空间是否不足超时 65 | K_RESPONSE_IS_EXIST_FILE_TIMEOUT, //判断文件是否存在超时 66 | K_RESPONSE_FILE_TRANSFER_TIMEOUT //文件传输超时 67 | }; 68 | 69 | //发送的命令类型 70 | #define FILE_HEAD_CODE 77 //发送文件头信息 71 | #define FILE_HEAD_REC_CODE 78 //接收文件头响应 72 | #define FILE_CANCEL 79 //发送取消文件传输信息 73 | #define FILE_REC_CANCEL 80 //接收取消传输响应 74 | #define FILE_CODE 81 //发送文件数据 75 | #define FILE_REC_CODE 82 //接收文件响应 76 | #define FILE_IS_EXIST_CODE 83 //发送查询文件是否存在请求 77 | #define FILE_IS_EXIST_REC_CODE 84 //接收查询文件是否存在响应 78 | #define FILE_IS_DISK_FREE_SPACE_CODE 85 //发送查询磁盘空间是否不足 79 | #define FILE_IS_DISK_FREE_SPACE_REC_CODE 86 //接收查询磁盘空间是否不足响应 80 | 81 | //服务端通知客户端 82 | #define FILE_TRANSFER_TIMEOUT_CODE 100 //文件传输超时,服务端主动通知客户端 83 | #define FILE_TRANSFER_FINISH_CODE 101 //文件传输完成 84 | 85 | 86 | typedef struct _checkfileStru 87 | { 88 | QString filePath; 89 | qint64 fileSize = 0; 90 | QString md5Str; 91 | bool bExist = true; 92 | } checkfileStru; 93 | 94 | 95 | #endif // CONFIG_H 96 | -------------------------------------------------------------------------------- /tcpClient/kfiletransfercachemanage.cpp: -------------------------------------------------------------------------------- 1 | //#include "stdafx.h" 2 | #include "kfiletransfercachemanage.h" 3 | #include 4 | #include 5 | 6 | KFileTransferCacheManage::KFileTransferCacheManage() 7 | { 8 | 9 | } 10 | 11 | qint64 KFileTransferCacheManage::getDiskFreeSpace(const QString& driver) 12 | { 13 | if (driver.isEmpty()) 14 | { 15 | qDebug() << __FUNCTION__ << "driver content is empty."; 16 | return 0; 17 | } 18 | QStorageInfo storageInfo(driver); 19 | storageInfo.refresh(); 20 | return storageInfo.bytesFree(); 21 | } 22 | 23 | QString KFileTransferCacheManage::getFileMd5(QFile& file) 24 | { 25 | if (!file.open(QIODevice::ReadOnly)) 26 | return QByteArray(); 27 | QByteArray context = file.readAll(); 28 | file.close(); 29 | return QString(QCryptographicHash::hash(context, QCryptographicHash::Md5).toHex()); 30 | } 31 | -------------------------------------------------------------------------------- /tcpClient/kfiletransfercachemanage.h: -------------------------------------------------------------------------------- 1 | #ifndef KFILETRANSFERCACHEMANAGE_H 2 | #define KFILETRANSFERCACHEMANAGE_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "Singleton.h" 9 | 10 | class KFileTransferCacheManage 11 | { 12 | DECLARESINGLETON(KFileTransferCacheManage) 13 | public: 14 | static KFileTransferCacheManage* GetInstance() 15 | { 16 | return SINGLETON(KFileTransferCacheManage); 17 | } 18 | static QString getFileMd5(QFile& file); 19 | static qint64 getDiskFreeSpace(const QString& driver); //参数: driver---盘符, 返回值: 返回多少字节 20 | private: 21 | KFileTransferCacheManage(); 22 | }; 23 | 24 | #endif // KFILETRANSFERCACHEMANAGE_H 25 | -------------------------------------------------------------------------------- /tcpClient/main.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | #include 3 | 4 | int main(int argc, char *argv[]) 5 | { 6 | QApplication a(argc, argv); 7 | MainWindow w; 8 | w.show(); 9 | 10 | return a.exec(); 11 | } 12 | -------------------------------------------------------------------------------- /tcpClient/mainwindow.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | #include "ui_mainwindow.h" 3 | #include "kfiletransfercachemanage.h" 4 | #include 5 | 6 | MainWindow::MainWindow(QWidget *parent) : 7 | QMainWindow(parent), 8 | ui(new Ui::MainWindow) 9 | { 10 | ui->setupUi(this); 11 | mytcpsocket = new KFileTransferSender(parent); 12 | connect(mytcpsocket, SIGNAL(progressValue(const QString&, int)), this, SLOT(on_progressValueChanged(const QString&,int))); 13 | connect(mytcpsocket, SIGNAL(errorState(int,int)), this, SLOT(on_error_state(int, int))); 14 | connect(mytcpsocket, &KFileTransferSender::fileTransferFinish, this, [this]{ 15 | ui->progressBar->setValue(100); 16 | QMessageBox::information(this, "传输完成", "传输完成"); 17 | }); 18 | 19 | ui->btn_upFile->setEnabled(false); 20 | ui->btn_cancel->setEnabled(false); 21 | } 22 | 23 | MainWindow::~MainWindow() 24 | { 25 | delete ui; 26 | } 27 | 28 | void MainWindow::on_btn_connect_clicked() 29 | { 30 | //连接服务器 31 | bool bconnected = mytcpsocket->connect_to_server(IP, PORT_COMMAND); 32 | qDebug() << (bconnected ? "连接成功" : "连接超时"); 33 | } 34 | 35 | void MainWindow::on_btn_selectFile_clicked() 36 | { 37 | //打开文件 38 | QString filepath = QFileDialog::getOpenFileName(this, "open", "../"); 39 | ui->lineEdit->setText(filepath); 40 | if(!filepath.isEmpty()) 41 | { 42 | ui->btn_upFile->setEnabled(true); 43 | } 44 | } 45 | 46 | void MainWindow::on_btn_upFile_clicked() 47 | { 48 | //上传 49 | QString filePath = ui->lineEdit->text(); 50 | if (! filePath.isEmpty()) 51 | { 52 | mytcpsocket->sendFile(filePath); 53 | } 54 | } 55 | 56 | void MainWindow::on_btn_cancel_clicked() 57 | { 58 | //取消上传 59 | mytcpsocket->cancelSendFile(); 60 | } 61 | 62 | void MainWindow::on_progressValueChanged(const QString& fileName, int progressVal) 63 | { 64 | qDebug() << "current transfer fileName===>" << fileName << ",progressVal===>" << progressVal; 65 | ui->progressBar->setValue(progressVal); 66 | 67 | ui->btn_cancel->setEnabled(progressVal); 68 | } 69 | 70 | void MainWindow::on_error_state(int code, int subCode) 71 | { 72 | qDebug() << __FUNCTION__ << " error: code=" << code << "\tsubCode=" << subCode; 73 | } 74 | 75 | void MainWindow::on_btn_freeDiskCheck_clicked() 76 | { 77 | QString filePath = ui->lineEdit->text(); 78 | QFileInfo fileInfo(filePath); 79 | if (fileInfo.isFile()) 80 | { 81 | bool bDiskFreeSpace = mytcpsocket->isDiskFreeSpace(fileInfo.size()); 82 | qDebug() << (bDiskFreeSpace ? "缓存目录有多余的磁盘空间 " : "缓存目录没有多余的磁盘空间 "); 83 | } 84 | } 85 | 86 | void MainWindow::on_btn_isExistFile_clicked() 87 | { 88 | QString filePath = ui->lineEdit->text(); 89 | QFile file(filePath); 90 | if (file.exists()) 91 | { 92 | checkfileStru fileStru; 93 | fileStru.filePath = file.fileName(); 94 | fileStru.fileSize = file.size(); 95 | fileStru.bExist = false; 96 | 97 | QStringList fileNameSplitList = filePath.split("."); 98 | QString fileSuffix = fileNameSplitList.last(); 99 | if (fileSuffix.compare("PPT", Qt::CaseInsensitive) == 0 || fileSuffix.compare("pptx", Qt::CaseInsensitive) == 0) 100 | { 101 | fileStru.md5Str = KFileTransferCacheManage::getFileMd5(file); 102 | } 103 | else 104 | { 105 | fileStru.md5Str = ""; 106 | } 107 | 108 | 109 | 110 | QList fileList; 111 | fileList.append(fileStru); 112 | mytcpsocket->isExistFile(fileList); 113 | 114 | for (checkfileStru fileInfo : fileList) 115 | { 116 | qDebug() << "fileName:" << fileInfo.filePath << (fileInfo.bExist ? " 服务器该文件存在 " : " 服务器该文件不存在 "); 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /tcpClient/mainwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINWINDOW_H 2 | #define MAINWINDOW_H 3 | 4 | #include 5 | #include "KFileTransferSender.h" 6 | #include 7 | 8 | namespace Ui { 9 | class MainWindow; 10 | } 11 | 12 | class MainWindow : public QMainWindow 13 | { 14 | Q_OBJECT 15 | 16 | public: 17 | explicit MainWindow(QWidget *parent = 0); 18 | ~MainWindow(); 19 | 20 | private slots: 21 | void on_btn_connect_clicked(); 22 | void on_btn_selectFile_clicked(); 23 | void on_btn_upFile_clicked(); 24 | void on_btn_cancel_clicked(); 25 | void on_progressValueChanged(const QString&,int); 26 | void on_error_state(int, int); 27 | void on_btn_freeDiskCheck_clicked(); 28 | 29 | void on_btn_isExistFile_clicked(); 30 | 31 | private: 32 | Ui::MainWindow *ui; 33 | KFileTransferSender *mytcpsocket; 34 | }; 35 | 36 | #endif // MAINWINDOW_H 37 | -------------------------------------------------------------------------------- /tcpClient/mainwindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 400 10 | 300 11 | 12 | 13 | 14 | MainWindow 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 第一步: 24 | 25 | 26 | 27 | 28 | 29 | 30 | 连接服务器 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 第二步: 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 选择文件 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 第三步: 67 | 68 | 69 | 70 | 71 | 72 | 73 | 检查服务端磁盘空间大小是否满足 74 | 75 | 76 | 77 | 78 | 79 | 80 | 检查服务端是否存在该文件 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 第三步: 92 | 93 | 94 | 95 | 96 | 97 | 98 | 上传选择的文件 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 100 110 | 111 | 112 | 0 113 | 114 | 115 | 116 | 117 | 118 | 119 | 取消发送 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | Qt::Vertical 129 | 130 | 131 | 132 | 20 133 | 85 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 0 144 | 0 145 | 400 146 | 23 147 | 148 | 149 | 150 | 151 | 152 | TopToolBarArea 153 | 154 | 155 | false 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /tcpClient/tcpClient.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2018-09-30T21:03:57 4 | # 5 | #------------------------------------------------- 6 | 7 | QT += core gui network concurrent testlib 8 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 9 | 10 | TARGET = tcpClient 11 | TEMPLATE = app 12 | 13 | CONFIG += c++11 14 | 15 | # The following define makes your compiler emit warnings if you use 16 | # any feature of Qt which has been marked as deprecated (the exact warnings 17 | # depend on your compiler). Please consult the documentation of the 18 | # deprecated API in order to know how to port your code away from it. 19 | DEFINES += QT_DEPRECATED_WARNINGS 20 | 21 | # You can also make your code fail to compile if you use deprecated APIs. 22 | # In order to do so, uncomment the following line. 23 | # You can also select to disable deprecated APIs only up to a certain version of Qt. 24 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 25 | 26 | 27 | SOURCES += \ 28 | main.cpp \ 29 | mainwindow.cpp \ 30 | KFileTransferSender.cpp \ 31 | kfiletransfercachemanage.cpp 32 | 33 | HEADERS += \ 34 | mainwindow.h \ 35 | config.h \ 36 | KFileTransferSender.h \ 37 | Singleton.h \ 38 | kfiletransfercachemanage.h 39 | 40 | FORMS += \ 41 | mainwindow.ui 42 | -------------------------------------------------------------------------------- /tcpServer/KFileTransferRecevicer.cpp: -------------------------------------------------------------------------------- 1 | //#include "stdafx.h" 2 | #include "KFileTransferRecevicer.h" 3 | #include "kfiletransfercachemanage.h" 4 | 5 | #include 6 | 7 | KFileTransferRecevicer::KFileTransferRecevicer(QObject *parent) 8 | : QObject(parent) 9 | , _bCancel(false) 10 | , m_bRunning(false) 11 | { 12 | QString cacheDir = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/mediaCache/"; 13 | setCacheDir(cacheDir); 14 | _pCommandSocket = new QTcpSocket(this); 15 | _pFileSocket = new QTcpSocket(this); 16 | _pTcpServerControl = new QTcpServer(this); 17 | _pTcpServerFile = new QTcpServer(this); 18 | _pFileSocket->setReadBufferSize(64*1024*1024); 19 | 20 | _pTcpServerControl->listen(QHostAddress::Any,PORT_COMMAND); 21 | _pTcpServerFile->listen(QHostAddress::Any,PORT_FILE); 22 | 23 | m_pTimerProgress = new QTimer(this); 24 | connect(m_pTimerProgress, &QTimer::timeout, this, &KFileTransferRecevicer::progress); 25 | m_pProgressTimeOut = new QTimer(this); 26 | connect(m_pProgressTimeOut, &QTimer::timeout, this, &KFileTransferRecevicer::timeOutCheck); 27 | 28 | connect(_pTcpServerControl,SIGNAL(newConnection()),this,SLOT(on_connect_c())); 29 | connect(_pTcpServerFile,SIGNAL(newConnection()),this,SLOT(on_connect_f())); 30 | } 31 | 32 | bool KFileTransferRecevicer::isExistFileInCacheDir(const QString &fileName, qint64 fileSize, const QString& md5Str) 33 | { 34 | QFile file(_fileCacheDir + fileName); 35 | qDebug() << __FUNCTION__ << file.fileName(); 36 | if (file.exists()) 37 | { 38 | //注意:此处的MD5码应该到数据库中查询获取,不能进行计算来获取。 39 | //因为计算需要时间,很可能导致响应超时,所以现在将发送端超时响应时间改为了3s; 40 | QStringList fileNameSplitList = fileName.split("."); 41 | QString fileSuffix = fileNameSplitList.last(); 42 | if (fileSuffix.compare("PPT", Qt::CaseInsensitive) == 0 || fileSuffix.compare("pptx", Qt::CaseInsensitive) == 0) 43 | { 44 | QString md5 = KFileTransferCacheManage::GetInstance()->getFileMd5(file); 45 | return ((file.size() == fileSize) && (md5 == md5Str)); 46 | } 47 | else 48 | { 49 | return file.size() == fileSize; 50 | } 51 | } 52 | return false; 53 | } 54 | 55 | void KFileTransferRecevicer::setCacheDir(const QString &dir) 56 | { 57 | QDir mdir(dir); 58 | if (! mdir.exists()) 59 | { 60 | mdir.mkdir(dir); 61 | qDebug() << __FUNCTION__ << "缓存目录创建成功"; 62 | } 63 | _fileCacheDir = dir; 64 | } 65 | 66 | void KFileTransferRecevicer::on_connect_c(){ 67 | _pCommandSocket = _pTcpServerControl->nextPendingConnection(); 68 | 69 | QString ip = _pCommandSocket->peerAddress().toString(); 70 | quint16 port = _pCommandSocket->peerPort(); 71 | 72 | qDebug()<%1:%2]成功连接").arg(ip).arg(port); 73 | _pCommandSocket->disconnect(); 74 | connect(_pCommandSocket,SIGNAL(readyRead()),this,SLOT(on_read_command())); 75 | connect(_pCommandSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onCommandError(QAbstractSocket::SocketError))); 76 | } 77 | 78 | void KFileTransferRecevicer::on_connect_f(){ 79 | _pFileSocket = _pTcpServerFile->nextPendingConnection(); 80 | 81 | QString ip = _pFileSocket->peerAddress().toString(); 82 | quint16 port = _pFileSocket->peerPort(); 83 | 84 | qDebug()<%1:%2]成功连接").arg(ip).arg(port); 85 | _pFileSocket->disconnect(); 86 | connect(_pFileSocket,SIGNAL(readyRead()),this,SLOT(on_read_file())); 87 | connect(_pFileSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onFileError(QAbstractSocket::SocketError))); 88 | _startTimeFlag = true; 89 | } 90 | 91 | void KFileTransferRecevicer::progress() 92 | { 93 | send_command(FILE_REC_CODE, K_SUCCEED, QString::number(_recvSize)); 94 | 95 | if (_fileSize > 0) 96 | { 97 | qDebug() << "******已接收数据百分比:" << (_recvSize * 100) / _fileSize; 98 | } 99 | if (_recvSize == _fileSize) 100 | { 101 | send_command(FILE_TRANSFER_FINISH_CODE, K_SUCCEED, QString::number(_recvSize)); 102 | m_pTimerProgress->stop(); 103 | m_pProgressTimeOut->stop(); 104 | qDebug() << __FUNCTION__ << "文件" << _fileName << "接收完成"; 105 | } 106 | } 107 | 108 | void KFileTransferRecevicer::timeOutCheck() 109 | { 110 | if (m_pTimerProgress->isActive() && (_recvSize != _fileSize) && (_recvSize != 0) && (_recvSize == _recvSize4Before)) 111 | { 112 | //发送传输超时 113 | send_command(FILE_TRANSFER_TIMEOUT_CODE, K_ERROR, ERROR_CODE_11); 114 | m_pProgressTimeOut->stop(); 115 | } 116 | _recvSize4Before = _recvSize; 117 | } 118 | 119 | int g_index = 0; 120 | void KFileTransferRecevicer::send_command(int code, int ret, QString additional) 121 | { 122 | QByteArray data; 123 | QDataStream in(&data, QIODevice::WriteOnly); 124 | in.setVersion(QDataStream::Qt_5_9); 125 | QString head = QString("%1" + QString(SPLIT_TYPE_INFO_MAEK) + "%2" + SPLIT_TYPE_INFO_MAEK +"%3").arg(code).arg(ret).arg(additional); 126 | //QString head = QString("%1##%2##%3").arg(code).arg(ret).arg(additional); 127 | in << qint64(2) << head.toUtf8(); 128 | in.device()->seek(0); 129 | 130 | g_index++; 131 | 132 | qDebug() << "before write" << g_index; 133 | in << qint64(data.size() - sizeof(qint64)); 134 | qint64 len = _pCommandSocket->write(data); 135 | _pCommandSocket->waitForBytesWritten(-1); 136 | qDebug() << "end write" << g_index; 137 | if(len <= 0) 138 | { 139 | qDebug()<<"命令发送失败 "<readAll(); 150 | int code = QString(buf).section(SPLIT_TYPE_INFO_MAEK,0,0).toInt(); 151 | QString additionalInfo = QString(buf).section(SPLIT_TYPE_INFO_MAEK,1,1); 152 | switch (code) 153 | { 154 | case FILE_HEAD_CODE: 155 | { 156 | quitFileTransferThread(); 157 | if (additionalInfo.isEmpty()) { qDebug() << ERROR_CODE_4; return; } 158 | _absoluteFilePathInHost = additionalInfo.section(SPLIT_ADDITION_INFO_MARK, 0, 0); 159 | _fileName = _absoluteFilePathInHost.right(_absoluteFilePathInHost.size() - _absoluteFilePathInHost.lastIndexOf('/') - 1); 160 | _fileSize = additionalInfo.section(SPLIT_ADDITION_INFO_MARK, 1, 1).toLongLong(); 161 | _recvSize = 0; 162 | _recvSize4Before = 0; 163 | 164 | 165 | ///////////////////////////////////////////////// 166 | //TODO: 这里判断 167 | //1.磁盘的大小是否足够, 168 | //2.文件是否已经存在等信息 169 | 170 | if (_file.isOpen()) 171 | { 172 | _file.close(); 173 | } 174 | 175 | QDir::setCurrent(_fileCacheDir); 176 | _file.setFileName(_fileName); 177 | bool isOk = _file.open(QIODevice::WriteOnly); 178 | if(false == isOk) 179 | { 180 | qDebug()<< __FUNCTION__ << __LINE__ << "writeonly error."; 181 | _pCommandSocket->disconnectFromHost(); 182 | _pCommandSocket->close(); 183 | return; 184 | } 185 | 186 | qDebug()<stop(); 209 | m_pProgressTimeOut->stop(); 210 | send_command(FILE_REC_CANCEL, K_SUCCEED, SUCCEED_CODE_3); 211 | qDebug() << __FUNCTION__ << __LINE__ << "已取消********"; 212 | } 213 | else 214 | { 215 | send_command(FILE_REC_CANCEL, K_ERROR, ERROR_CODE_7); 216 | } 217 | break; 218 | } 219 | case FILE_IS_EXIST_CODE: 220 | { 221 | if (additionalInfo.isEmpty()) { qDebug() << ERROR_CODE_8; return; } 222 | QString fileName = additionalInfo.section(SPLIT_ADDITION_INFO_MARK, 0, 0); 223 | qint64 fileSize = additionalInfo.section(SPLIT_ADDITION_INFO_MARK, 1, 1).toLongLong(); 224 | QString md5Str = additionalInfo.section(SPLIT_ADDITION_INFO_MARK, 2, 2); 225 | 226 | fileName = fileName.right(fileName.size()-fileName.lastIndexOf('/') - 1); 227 | 228 | if (isExistFileInCacheDir(fileName, fileSize, md5Str)) 229 | { 230 | send_command(FILE_IS_EXIST_REC_CODE, K_SUCCEED, SUCCEED_CODE_4); 231 | } 232 | else 233 | { 234 | send_command(FILE_IS_EXIST_REC_CODE, K_ERROR, ERROR_CODE_10); 235 | } 236 | break; 237 | } 238 | case FILE_IS_DISK_FREE_SPACE_CODE: 239 | { 240 | //TODO: 判断添加文件后是否会空间不足; 241 | qint64 fileSize = additionalInfo.toLongLong(); 242 | QString sreachDir = ""; 243 | #ifdef Q_OS_WIN 244 | sreachDir = _fileCacheDir.left(2); 245 | #elif Q_OS_LINUX 246 | sreachDir = "/" + _fileCacheDir.section("/", 0, 0); 247 | #endif 248 | qint64 freeSpaceSize = KFileTransferCacheManage::getDiskFreeSpace(sreachDir); 249 | if (fileSize <= freeSpaceSize) 250 | { 251 | send_command(FILE_IS_DISK_FREE_SPACE_REC_CODE, K_SUCCEED, SUCCEED_CODE_5); 252 | } 253 | else 254 | { 255 | send_command(FILE_IS_DISK_FREE_SPACE_REC_CODE, K_ERROR, ERROR_CODE_6); 256 | } 257 | break; 258 | } 259 | } 260 | } 261 | 262 | 263 | void KFileTransferRecevicer::beginSave() 264 | { 265 | while (true) 266 | { 267 | if (_bCancel) break; 268 | 269 | m_byteArrayListLock.lockForWrite(); 270 | if (m_ByteArrayList.size() > 0 && _file.isOpen()) 271 | { 272 | QByteArray buff = m_ByteArrayList.front(); 273 | m_ByteArrayList.pop_front(); 274 | 275 | m_byteArrayListLock.unlock(); 276 | 277 | qint64 len = _file.write(buff); 278 | if (len > 0) 279 | _recvSize += len; 280 | } 281 | else 282 | { 283 | m_byteArrayListLock.unlock(); 284 | 285 | if (_recvSize == _fileSize) 286 | { 287 | qint64 msec = _startTime.msecsTo(QDateTime::currentDateTime()); 288 | if (msec) qDebug() << "接收数据时间为:" << msec << "ms, \t速率:" << (_fileSize * 1000) / (1024 * 1024 * msec) << "MB/S"; 289 | QDir::setCurrent(_fileCacheDir); 290 | _file.close(); 291 | qDebug() << "文件缓存路径:" << _fileCacheDir; 292 | break; 293 | } 294 | QThread::msleep(10); 295 | } 296 | } 297 | qDebug() << __FUNCTION__ << "****已中断文件传输线程***" << "\t_bCancel===>" << _bCancel; 298 | m_bRunning = false; 299 | } 300 | 301 | void KFileTransferRecevicer::quitFileTransferThread() 302 | { 303 | while (m_bRunning) 304 | { 305 | _bCancel = true; 306 | QThread::msleep(10); 307 | } 308 | } 309 | 310 | void KFileTransferRecevicer::on_read_file() 311 | { 312 | if (_startTimeFlag) 313 | { 314 | _startTime = QDateTime::currentDateTime(); 315 | _startTimeFlag = false; 316 | 317 | m_byteArrayListLock.lockForWrite(); 318 | m_ByteArrayList.clear(); 319 | m_byteArrayListLock.unlock(); 320 | m_pTimerProgress->start(500); 321 | m_pProgressTimeOut->start(3000); 322 | qDebug() << __FUNCTION__ << "***开始读取文件数据***" << "\t_bCancel===>" << _bCancel; 323 | 324 | m_bRunning = true; 325 | _bCancel = false; 326 | QtConcurrent::run([this] { beginSave(); }); 327 | } 328 | 329 | if (_pFileSocket->bytesAvailable()) 330 | { 331 | QByteArray buf = _pFileSocket->readAll(); 332 | m_byteArrayListLock.lockForWrite(); 333 | m_ByteArrayList.push_back(buf); 334 | m_byteArrayListLock.unlock(); 335 | 336 | // if (!m_bRunning) 337 | // { 338 | // m_bRunning = true; 339 | // QtConcurrent::run([this] { beginSave(); }); 340 | // } 341 | } 342 | } 343 | 344 | void KFileTransferRecevicer::onFileError(QAbstractSocket::SocketError) 345 | { 346 | qDebug() << "file_socket error:" << _pFileSocket->errorString(); 347 | //quitFileTransferThread(); 348 | } 349 | 350 | void KFileTransferRecevicer::onCommandError(QAbstractSocket::SocketError) 351 | { 352 | qDebug() << "command_socket error:" << _pCommandSocket->errorString(); 353 | } 354 | -------------------------------------------------------------------------------- /tcpServer/KFileTransferRecevicer.cpp.bak: -------------------------------------------------------------------------------- 1 | //#include "stdafx.h" 2 | #include "KFileTransferRecevicer.h" 3 | #include "kfiletransfercachemanage.h" 4 | 5 | #include 6 | 7 | KFileTransferRecevicer::KFileTransferRecevicer(QObject *parent) 8 | : QObject(parent) 9 | , _bCancel(false) 10 | { 11 | QString cacheDir = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/mediaCache/"; 12 | setCacheDir(cacheDir); 13 | _pCommandSocket = new QTcpSocket(this); 14 | _pFileSocket = new QTcpSocket(this); 15 | _pTcpServerControl = new QTcpServer(this); 16 | _pTcpServerFile = new QTcpServer(this); 17 | _pFileSocket->setReadBufferSize(64*1024*1024); 18 | 19 | _pTcpServerControl->listen(QHostAddress::Any,PORT_COMMAND); 20 | _pTcpServerFile->listen(QHostAddress::Any,PORT_FILE); 21 | 22 | connect(_pTcpServerControl,SIGNAL(newConnection()),this,SLOT(on_connect_c())); 23 | connect(_pTcpServerFile,SIGNAL(newConnection()),this,SLOT(on_connect_f())); 24 | } 25 | 26 | bool KFileTransferRecevicer::isExistFileInCacheDir(const QString &fileName, qint64 fileSize) 27 | { 28 | QFileInfo info(_fileCacheDir + "/" + fileName); 29 | qDebug() << __FUNCTION__ << info.absoluteFilePath(); 30 | return (info.exists() && (info.size() == fileSize)); 31 | } 32 | 33 | void KFileTransferRecevicer::setCacheDir(const QString &dir) 34 | { 35 | QDir mdir(dir); 36 | if (! mdir.exists()) 37 | { 38 | mdir.mkdir(dir); 39 | qDebug() << __FUNCTION__ << "缓存目录创建成功"; 40 | } 41 | _fileCacheDir = dir; 42 | } 43 | 44 | void KFileTransferRecevicer::on_connect_c(){ 45 | _pCommandSocket = _pTcpServerControl->nextPendingConnection(); 46 | 47 | QString ip = _pCommandSocket->peerAddress().toString(); 48 | quint16 port = _pCommandSocket->peerPort(); 49 | 50 | qDebug()<disconnect(); 52 | connect(_pCommandSocket,SIGNAL(readyRead()),this,SLOT(on_read_command())); 53 | connect(_pCommandSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onCommandError(QAbstractSocket::SocketError))); 54 | } 55 | 56 | void KFileTransferRecevicer::on_connect_f(){ 57 | _pFileSocket = _pTcpServerFile->nextPendingConnection(); 58 | 59 | QString ip = _pFileSocket->peerAddress().toString(); 60 | quint16 port = _pFileSocket->peerPort(); 61 | 62 | qDebug()<disconnect(); 64 | connect(_pFileSocket,SIGNAL(readyRead()),this,SLOT(on_read_file())); 65 | connect(_pFileSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onFileError(QAbstractSocket::SocketError))); 66 | _startTimeFlag = true; 67 | } 68 | 69 | void KFileTransferRecevicer::send_command(int code, int ret, QString additional) 70 | { 71 | QByteArray data; 72 | QDataStream in(&data, QIODevice::WriteOnly); 73 | in.setVersion(QDataStream::Qt_5_9); 74 | QString head = QString("%1" + QString(SPLIT_TYPE_INFO_MAEK) + "%2" + SPLIT_TYPE_INFO_MAEK +"%3").arg(code).arg(ret).arg(additional); 75 | //QString head = QString("%1##%2##%3").arg(code).arg(ret).arg(additional); 76 | in << qint64(2) << head; 77 | in.device()->seek(0); 78 | in << qint64(data.size() - sizeof(qint64)); 79 | qint64 len = _pCommandSocket->write(data); 80 | _pCommandSocket->waitForBytesWritten(-1); 81 | if(len <= 0) 82 | { 83 | qDebug()<<"命令发送失败 "<readAll(); 94 | int code = QString(buf).section(SPLIT_TYPE_INFO_MAEK,0,0).toInt(); 95 | QString additionalInfo = QString(buf).section(SPLIT_TYPE_INFO_MAEK,1,1); 96 | switch (code) 97 | { 98 | case FILE_HEAD_CODE: 99 | { 100 | if (additionalInfo.isEmpty()) { qDebug() << ERROR_CODE_4; return; } 101 | _fileName = additionalInfo.section(SPLIT_ADDITION_INFO_MARK, 0, 0); 102 | _fileSize = additionalInfo.section(SPLIT_ADDITION_INFO_MARK, 1, 1).toLongLong(); 103 | _recvSize = 0; 104 | _bCancel = false; 105 | 106 | ///////////////////////////////////////////////// 107 | //TODO: 这里判断 108 | //1.磁盘的大小是否足够, 109 | //2.文件是否已经存在等信息 110 | 111 | QDir::setCurrent(_fileCacheDir); 112 | _file.setFileName(_fileName); 113 | bool isOk = _file.open(QIODevice::WriteOnly); 114 | if(false == isOk) 115 | { 116 | qDebug()<< __FUNCTION__ << __LINE__ << "writeonly error."; 117 | _pCommandSocket->disconnectFromHost(); 118 | _pCommandSocket->close(); 119 | return; 120 | } 121 | 122 | qDebug()<bytesAvailable(); 207 | if ((dataSize >= SEND_BLOCK_SIZE) || (dataSize == (_fileSize - _recvSize))) 208 | { 209 | QByteArray buf = _pFileSocket->readAll(); 210 | //qint64 len = buf.size(); 211 | qint64 len = _file.write(buf); 212 | 213 | if(len > 0) 214 | { 215 | _recvSize += len; 216 | qDebug()<< "接收的文件数据大小为:" << len / 1024 << "KB" << "\t已接收的数据大小为:" << _recvSize / 1024 << "KB"; 217 | } 218 | 219 | QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); //让系统去处理其他的接收命令 220 | send_command(FILE_REC_CODE, K_SUCCEED, QString::number(_recvSize)); 221 | 222 | if(_recvSize == _fileSize) 223 | { 224 | qint64 msec = _startTime.msecsTo(QDateTime::currentDateTime()); 225 | if (msec) qDebug() << "接收数据时间为:" << msec << "ms, \t速率:"<< (_fileSize * 1000) / (1024*1024* msec) << "MB/S"; 226 | QDir::setCurrent(_fileCacheDir); 227 | _file.close(); 228 | } 229 | } 230 | } 231 | 232 | void KFileTransferRecevicer::onFileError(QAbstractSocket::SocketError) 233 | { 234 | qDebug() << "file_socket error:" << _pFileSocket->errorString(); 235 | } 236 | 237 | void KFileTransferRecevicer::onCommandError(QAbstractSocket::SocketError) 238 | { 239 | qDebug() << "command_socket error:" << _pCommandSocket->errorString(); 240 | } 241 | -------------------------------------------------------------------------------- /tcpServer/KFileTransferRecevicer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "config.h" 4 | #include "Singleton.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | class KFileTransferRecevicer:public QObject 15 | { 16 | Q_OBJECT 17 | DECLARESINGLETON(KFileTransferRecevicer) 18 | public: 19 | static KFileTransferRecevicer* GetInstance() 20 | { 21 | return SINGLETON(KFileTransferRecevicer); 22 | } 23 | void send_command(int code, int ret, QString additional = ""); 24 | public slots: 25 | void on_read_command(); 26 | void on_read_file(); 27 | void onFileError(QAbstractSocket::SocketError); 28 | void onCommandError(QAbstractSocket::SocketError); 29 | void on_connect_c(); 30 | void on_connect_f(); 31 | void progress(); 32 | void timeOutCheck(); 33 | private: 34 | explicit KFileTransferRecevicer(QObject *parent = nullptr); 35 | bool isExistFileInCacheDir(const QString& fileName, qint64 fileSize, const QString& md5Str); 36 | void setCacheDir(const QString& dir); 37 | 38 | void beginSave(); 39 | void quitFileTransferThread(); 40 | private: 41 | QTcpSocket *_pCommandSocket; 42 | QTcpSocket *_pFileSocket; 43 | QTcpServer *_pTcpServerControl; 44 | QTcpServer *_pTcpServerFile; 45 | 46 | QFile _file; 47 | QString _absoluteFilePathInHost; //文件在主机中的路径,包含文件名 48 | QString _fileName; //文件路径名称 49 | qint64 _fileSize; //传输文件大小 50 | qint64 _recvSize; //接收数据大小 51 | QString _fileCacheDir; //文件缓存路径 52 | 53 | bool _bCancel; //是否取消传输 54 | QDateTime _startTime; //传输开始时间记录对象 55 | bool _startTimeFlag; //传输开始时间记录标识 56 | QTimer* m_pTimerProgress; //定时获取已接收数据大小定时器 57 | bool m_bRunning; 58 | QByteArrayList m_ByteArrayList; //接收数据缓存队列 59 | QReadWriteLock m_byteArrayListLock; //接收数据缓存队列读写锁 60 | 61 | QTimer* m_pProgressTimeOut; //传输超时监测定时器 62 | qint64 _recvSize4Before; //定时检测数据,记录上一次已接收数据大小 63 | }; 64 | 65 | -------------------------------------------------------------------------------- /tcpServer/KFileTransferRecevicer.h.bak: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "config.h" 4 | #include "Singleton.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | class KFileTransferRecevicer:public QObject 15 | { 16 | Q_OBJECT 17 | DECLARESINGLETON(KFileTransferRecevicer) 18 | public: 19 | static KFileTransferRecevicer* GetInstance() 20 | { 21 | return SINGLETON(KFileTransferRecevicer); 22 | } 23 | void send_command(int code, int ret, QString additional = ""); 24 | public slots: 25 | void on_read_command(); 26 | void on_read_file(); 27 | void onFileError(QAbstractSocket::SocketError); 28 | void onCommandError(QAbstractSocket::SocketError); 29 | void on_connect_c(); 30 | void on_connect_f(); 31 | private: 32 | explicit KFileTransferRecevicer(QObject *parent = nullptr); 33 | bool isExistFileInCacheDir(const QString& fileName, qint64 fileSize); 34 | void setCacheDir(const QString& dir); 35 | QTcpSocket *_pCommandSocket; 36 | QTcpSocket *_pFileSocket; 37 | QTcpServer *_pTcpServerControl; 38 | QTcpServer *_pTcpServerFile; 39 | 40 | QFile _file; 41 | QString _fileName; 42 | qint64 _fileSize; 43 | qint64 _recvSize; 44 | QString _fileCacheDir; 45 | 46 | bool _bCancel; 47 | QDateTime _startTime; 48 | bool _startTimeFlag; 49 | }; 50 | 51 | -------------------------------------------------------------------------------- /tcpServer/Singleton.h: -------------------------------------------------------------------------------- 1 | #ifndef _KOMMANDER_TOOL_SINGLETON_H_ 2 | #define _KOMMANDER_TOOL_SINGLETON_H_ 3 | 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | //#include 9 | 10 | //typedef std::function DelSingletonAction; 11 | //typedef QQueue SingletonDeleteQueue; 12 | 13 | //void pushSingletonAction(DelSingletonAction delAction); 14 | //void clearSingleton(); 15 | 16 | template 17 | class KSingleton 18 | { 19 | public: 20 | template 21 | static T* instance(Args&&... args) 22 | { 23 | static T* _instance = nullptr; 24 | static std::once_flag oc; 25 | std::call_once(oc, [&] { 26 | _instance = new T(std::forward(args)...); 27 | }); 28 | return _instance; 29 | } 30 | 31 | private: 32 | KSingleton() {} 33 | virtual ~KSingleton() {} 34 | KSingleton(const KSingleton& st) {} 35 | KSingleton &operator=(const KSingleton& st) {} 36 | }; 37 | 38 | #define SINGLETON(x,...) KSingleton::instance(__VA_ARGS__) 39 | #define SINGLETONDELETE(x) { delete SINGLETON(x); } 40 | #define DECLARESINGLETON(clsname) friend class KSingleton; 41 | #define CLEARSINGLETON { clearSingleton(); } 42 | #endif 43 | 44 | 45 | -------------------------------------------------------------------------------- /tcpServer/config.h: -------------------------------------------------------------------------------- 1 | #ifndef CONFIG_H 2 | #define CONFIG_H 3 | 4 | #include 5 | 6 | #define IP "127.0.0.1" 7 | //#define IP "192.168.0.120" 8 | #define PORT_COMMAND 8888 9 | #define PORT_FILE 8848 10 | 11 | #define USE_THREAD_TRANSFER 12 | //#define USE_QTCREATOR 13 | 14 | #define SEND_BLOCK_SIZE (qint64)(4 * 1024 * 1024) 15 | 16 | #define SPLIT_TYPE_INFO_MAEK "##" 17 | #define SPLIT_ADDITION_INFO_MARK ",," 18 | 19 | #define K_ERROR false 20 | #define K_SUCCEED true 21 | 22 | #define ERROR_CODE_1 "设置的文件路径错误" 23 | #define ERROR_CODE_2 "要上传的文件打开失败" 24 | #define ERROR_CODE_3 "命令发送失败" 25 | #define ERROR_CODE_4 "文件头部信息接收失败" 26 | #define ERROR_CODE_5 "文件数据接收失败" 27 | #define ERROR_CODE_6 "磁盘空间已不足,无法存储该文件" 28 | #define ERROR_CODE_7 "不能再次点击取消操作" 29 | #define ERROR_CODE_8 "查询文件是否存在,附加信息错误" 30 | #define ERROR_CODE_9 "设置的缓存目录错误" 31 | #define ERROR_CODE_10 "文件在缓存中不存在" 32 | #define ERROR_CODE_11 "文件传输超时" 33 | 34 | #define SUCCEED_CODE_1 "文件头部信息接收成功" 35 | #define SUCCEED_CODE_2 "接收端文件数据接收完成" 36 | #define SUCCEED_CODE_3 "接收端文件取消完成" 37 | #define SUCCEED_CODE_4 "文件在缓存中存在" 38 | #define SUCCEED_CODE_5 "磁盘空间大小足够存储该文件" 39 | 40 | //错误分类 41 | enum ERROR_CLASSIFY_EM 42 | { 43 | K_FILE_TRANSFER_ERROR = 100, 44 | K_NETWORK_ERROR = K_FILE_TRANSFER_ERROR + 200, 45 | K_RESPONSE_TIMEOUT = K_NETWORK_ERROR + 200 46 | }; 47 | 48 | //文件传输错误 49 | enum K_FILE_TRANSFER_ERROR_EM 50 | { 51 | K_FILE_TRANSFER_CANCEL_ERROR = ERROR_CLASSIFY_EM::K_FILE_TRANSFER_ERROR + 1 //传输取消错误 52 | }; 53 | 54 | //网络错误 55 | enum K_NETWORK_ERROR_EM 56 | { 57 | K_NETWORK_DISCONNECTED_COMMAND_ERROR = ERROR_CLASSIFY_EM::K_NETWORK_ERROR + 1, //网络连接命令socket错误 58 | K_NETWORK_DISCONNECTED_FILE_ERROR //网络连接文件socket错误 59 | }; 60 | 61 | enum K_RESPONSE_TIMEOUT_EM 62 | { 63 | K_RESPONSE_CANCEL_FILE_TIMEOUT = ERROR_CLASSIFY_EM::K_RESPONSE_TIMEOUT + 1, //取消文件超时 64 | K_RESPONSE_IS_DISK_FREE_SPACE_FILE_TIMEOUT, //判断磁盘空间是否不足超时 65 | K_RESPONSE_IS_EXIST_FILE_TIMEOUT, //判断文件是否存在超时 66 | K_RESPONSE_FILE_TRANSFER_TIMEOUT //文件传输超时 67 | }; 68 | 69 | //发送的命令类型 70 | #define FILE_HEAD_CODE 77 //发送文件头信息 71 | #define FILE_HEAD_REC_CODE 78 //接收文件头响应 72 | #define FILE_CANCEL 79 //发送取消文件传输信息 73 | #define FILE_REC_CANCEL 80 //接收取消传输响应 74 | #define FILE_CODE 81 //发送文件数据 75 | #define FILE_REC_CODE 82 //接收文件响应 76 | #define FILE_IS_EXIST_CODE 83 //发送查询文件是否存在请求 77 | #define FILE_IS_EXIST_REC_CODE 84 //接收查询文件是否存在响应 78 | #define FILE_IS_DISK_FREE_SPACE_CODE 85 //发送查询磁盘空间是否不足 79 | #define FILE_IS_DISK_FREE_SPACE_REC_CODE 86 //接收查询磁盘空间是否不足响应 80 | 81 | //服务端通知客户端 82 | #define FILE_TRANSFER_TIMEOUT_CODE 100 //文件传输超时,服务端主动通知客户端 83 | #define FILE_TRANSFER_FINISH_CODE 101 //文件传输完成 84 | 85 | 86 | typedef struct _checkfileStru 87 | { 88 | QString filePath; 89 | qint64 fileSize = 0; 90 | QString md5Str; 91 | bool bExist = true; 92 | } checkfileStru; 93 | 94 | 95 | #endif // CONFIG_H 96 | -------------------------------------------------------------------------------- /tcpServer/kfiletransfercachemanage.cpp: -------------------------------------------------------------------------------- 1 | //#include "stdafx.h" 2 | #include "kfiletransfercachemanage.h" 3 | #include 4 | #include 5 | 6 | KFileTransferCacheManage::KFileTransferCacheManage() 7 | { 8 | 9 | } 10 | 11 | qint64 KFileTransferCacheManage::getDiskFreeSpace(const QString& driver) 12 | { 13 | if (driver.isEmpty()) 14 | { 15 | qDebug() << __FUNCTION__ << "driver content is empty."; 16 | return 0; 17 | } 18 | QStorageInfo storageInfo(driver); 19 | storageInfo.refresh(); 20 | return storageInfo.bytesFree(); 21 | } 22 | 23 | QString KFileTransferCacheManage::getFileMd5(QFile& file) 24 | { 25 | if (!file.open(QIODevice::ReadOnly)) 26 | return QByteArray(); 27 | QByteArray context = file.readAll(); 28 | file.close(); 29 | return QString(QCryptographicHash::hash(context, QCryptographicHash::Md5).toHex()); 30 | } 31 | -------------------------------------------------------------------------------- /tcpServer/kfiletransfercachemanage.h: -------------------------------------------------------------------------------- 1 | #ifndef KFILETRANSFERCACHEMANAGE_H 2 | #define KFILETRANSFERCACHEMANAGE_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "Singleton.h" 9 | 10 | class KFileTransferCacheManage 11 | { 12 | DECLARESINGLETON(KFileTransferCacheManage) 13 | public: 14 | static KFileTransferCacheManage* GetInstance() 15 | { 16 | return SINGLETON(KFileTransferCacheManage); 17 | } 18 | static QString getFileMd5(QFile& file); 19 | static qint64 getDiskFreeSpace(const QString& driver); //参数: driver---盘符, 返回值: 返回多少字节 20 | private: 21 | KFileTransferCacheManage(); 22 | }; 23 | 24 | #endif // KFILETRANSFERCACHEMANAGE_H 25 | -------------------------------------------------------------------------------- /tcpServer/ksqlobject.cpp: -------------------------------------------------------------------------------- 1 | #include "ksqlobject.h" 2 | 3 | #include 4 | 5 | KSqliteDBAOperator::KSqliteDBAOperator() 6 | { 7 | _database = QSqlDatabase::addDatabase("QSQLITE"); 8 | } 9 | 10 | KSqliteDBAOperator::~KSqliteDBAOperator() 11 | { 12 | if (_database.isOpen()) 13 | { 14 | _database.close(); 15 | } 16 | } 17 | 18 | bool KSqliteDBAOperator::open(const QString& databaseName) 19 | { 20 | _database.setDatabaseName(databaseName); 21 | bool ret = _database.open(); 22 | if (!ret) 23 | { 24 | qDebug() << "Error: Failed to connect database." << _database.lastError(); 25 | } 26 | else 27 | { 28 | qDebug() << "Succeed to connect database." ; 29 | } 30 | return ret; 31 | } 32 | -------------------------------------------------------------------------------- /tcpServer/ksqlobject.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | class KSqliteDBAOperator 8 | { 9 | public: 10 | explicit KSqliteDBAOperator(); 11 | ~KSqliteDBAOperator(); 12 | bool open(const QString& databaseName); //打开数据库 13 | bool exec(const QString& sqlCmd); //数据库指令执行 14 | bool deleteDB(); //删除数据库 15 | bool isExistTable(); //数据库表是否存在; 16 | private: 17 | QSqlDatabase _database; 18 | }; 19 | -------------------------------------------------------------------------------- /tcpServer/main.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | #include 3 | 4 | int main(int argc, char *argv[]) 5 | { 6 | QApplication a(argc, argv); 7 | MainWindow w; 8 | w.show(); 9 | 10 | return a.exec(); 11 | } 12 | -------------------------------------------------------------------------------- /tcpServer/mainwindow.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | #include "ui_mainwindow.h" 3 | 4 | MainWindow::MainWindow(QWidget *parent) : 5 | QMainWindow(parent), 6 | ui(new Ui::MainWindow) 7 | { 8 | ui->setupUi(this); 9 | mytcpsocket = KFileTransferRecevicer::GetInstance(); 10 | } 11 | 12 | MainWindow::~MainWindow() 13 | { 14 | delete ui; 15 | } 16 | 17 | -------------------------------------------------------------------------------- /tcpServer/mainwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINWINDOW_H 2 | #define MAINWINDOW_H 3 | 4 | #include 5 | #include "KFileTransferRecevicer.h" 6 | 7 | namespace Ui { 8 | class MainWindow; 9 | } 10 | 11 | class MainWindow : public QMainWindow 12 | { 13 | Q_OBJECT 14 | 15 | public: 16 | explicit MainWindow(QWidget *parent = 0); 17 | ~MainWindow(); 18 | private: 19 | Ui::MainWindow *ui; 20 | KFileTransferRecevicer *mytcpsocket; 21 | }; 22 | 23 | #endif // MAINWINDOW_H 24 | -------------------------------------------------------------------------------- /tcpServer/mainwindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 400 10 | 300 11 | 12 | 13 | 14 | MainWindow 15 | 16 | 17 | 18 | 19 | 20 | 0 21 | 0 22 | 400 23 | 23 24 | 25 | 26 | 27 | 28 | 29 | TopToolBarArea 30 | 31 | 32 | false 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /tcpServer/tcpServer.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2018-10-02T13:53:25 4 | # 5 | #------------------------------------------------- 6 | 7 | QT += core gui sql 8 | QT += network 9 | QT += concurrent 10 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 11 | 12 | TARGET = tcpServer 13 | TEMPLATE = app 14 | 15 | CONFIG += c++11 16 | 17 | # The following define makes your compiler emit warnings if you use 18 | # any feature of Qt which has been marked as deprecated (the exact warnings 19 | # depend on your compiler). Please consult the documentation of the 20 | # deprecated API in order to know how to port your code away from it. 21 | DEFINES += QT_DEPRECATED_WARNINGS 22 | 23 | # You can also make your code fail to compile if you use deprecated APIs. 24 | # In order to do so, uncomment the following line. 25 | # You can also select to disable deprecated APIs only up to a certain version of Qt. 26 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 27 | 28 | 29 | SOURCES += \ 30 | main.cpp \ 31 | mainwindow.cpp \ 32 | KFileTransferRecevicer.cpp \ 33 | kfiletransfercachemanage.cpp \ 34 | ksqlobject.cpp 35 | 36 | HEADERS += \ 37 | mainwindow.h \ 38 | config.h \ 39 | KFileTransferRecevicer.h \ 40 | Singleton.h \ 41 | kfiletransfercachemanage.h \ 42 | ksqlobject.h 43 | 44 | FORMS += \ 45 | mainwindow.ui 46 | --------------------------------------------------------------------------------