很多初学者都会遇到这个坎,如何将Windows数据结构、网络编程等知识整合为完整的项目。
本文将深入解析一个基于C++ Qt开发的企业级文件传输系统,涵盖TCP通信、断点续传、SSL加密、SQLite持久化等核心技术。(项目源码来文章底部拿)
模块 |
作用 |
关键类 |
Qt Widgets |
GUI界面开发 |
QMainWindow, QDialog |
Qt Network |
TCP/UDP通信 |
QTcpServer, QTcpSocket |
Qt Core |
信号槽/事件循环/数据流 |
QObject, QDataStream |
Qt GUI |
绘图与样式定制 |
QPainter, QPalette |
信号槽机制实战:通过connect绑定Socket的readyRead信号到自定义槽函数,实现异步消息处理
connect(clientSocket, &QTcpSocket::readyRead,
this, &Server::onReadyRead);
// 服务端监听实现
void Server::startListen() {
m_tcpServer = new QTcpServer(this);
if(!m_tcpServer->listen(QHostAddress::Any, 6688)) {
qCritical() << "监听失败:" << m_tcpServer->errorString();
return;
}
connect(m_tcpServer, &QTcpServer::newConnection, this, &Server::handleNewConnection);
}
// SSL加密配置
void Server::initSSL() {
QSslCertificate cert = QSslCertificate::fromPath("server.crt");
QSslKey key(QFile("server.key").readAll(), QSsl::Rsa);
m_sslSocket->setPrivateKey(key);
m_sslSocket->setLocalCertificate(cert);
m_sslSocket->startServerEncryption();
}
// 文件分块传输逻辑
void FileSender::sendFileData() {
QFile file(m_filePath);
if (!file.open(QIODevice::ReadOnly)) return;
qint64 chunkSize = 4 * 1024; // 4KB分块
while (!file.atEnd()) {
QByteArray block = file.read(chunkSize);
m_socket->write(block);
m_sentBytes += block.size();
emit progressUpdated(m_sentBytes *100 / m_fileSize);
}
file.close();
}
// 断点续传实现
void FileReceiver::resumeTransfer() {
QFileInfo fileInfo(m_filePath);
qint64 existingSize = fileInfo.exists() ? fileInfo.size() : 0;
m_socket->write(QString("RESUME:%1").arg(existingSize).toUtf8());
}
┌───────────────┐ ┌───────────────┐
│ Client │ │ Server │
├───────────────┤ ├───────────────┤
│QTcpSocket │<----->│QTcpServer │
│QSslSocket │ │QSslSocket │
├───────────────┤ ├───────────────┤
│QDataStream │ │QDataStream │
│QByteArray │ │QFile │
└───────────────┘ └───────────────┘
// 系统托盘实现
void MainWindow::createTrayIcon() {
m_trayIcon = new QSystemTrayIcon(this);
QMenu *trayMenu = new QMenu(this);
trayMenu->addAction("恢复窗口", this, &MainWindow::showNormal);
trayMenu->addAction("退出", qApp, &QApplication::quit);
m_trayIcon->setContextMenu(trayMenu);
m_trayIcon->setIcon(QIcon(":/icon/app.ico"));
m_trayIcon->show();
}
// 界面绘制优化
void ChatWindow::paintEvent(QPaintEvent *) {
QPainter painter(this);
QLinearGradient gradient(0, 0, width(), height());
gradient.setColorAt(0, QColor("#2c3e50"));
gradient.setColorAt(1, QColor("#3498db"));
painter.fillRect(rect(), gradient);
}
graph TD
A[打开文件QFile] --> B[读取4KB数据块]
B --> C{是否读取完毕?}
C -- 否 --> D[写入Socket缓冲区]
D --> E[更新进度条: sentBytes+=4KB]
C -- 是 --> F[关闭文件并发送完成信号]
// 服务端记录传输状态
QMap transferProgress;
// 客户端请求续传时发送已接收字节数
qint64 resumePos = file.size();
socket->write((char*)&resumePos, sizeof(qint64));
# 生成证书
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365
QSslSocket *sslSocket = new QSslSocket(this);
sslSocket->setPrivateKey("key.pem");
sslSocket->setLocalCertificate("cert.pem");
CREATE TABLE IF NOT EXISTS messages (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
content BLOB,
is_file BOOLEAN
);
通过这个项目,开发者可以掌握:
建议开发路线:先从消息通信入手,逐步增加文件传输功能,最后实现加密等高级特性。