Qt使用QTcpSocket及QTcpServer传输文件

服务端具体代码如下:

.h
#include <QTcpServer>
#include <QTcpSocket>
#include <QFileDialog>
#include <QFile>
#define BUF_SIZE 1024*8
class ServerProject : public QWidget
{
    Q_OBJECT

public:
    ServerProject(QWidget *parent = nullptr);
    ~ServerProject();
    void iniServer();
    void closeServer();
    void sendData();
private slots:
    void on_listenBtn_clicked();
    void on_sendBtn_clicked();
    void on_clearRecBtn_clicked();
    void on_selectBtn_clicked();
    void on_sendFileBtn_clicked();
    void newConnectionSlot();
    void readyReadSlot();
private:
    Ui::ServerProjectClass ui;
	QTcpServer* m_server;
    QTcpSocket* m_socket;
    QString m_filename;
    int m_fileSize, m_sendSize;
    QFile m_file;
};
.cpp
ServerProject::ServerProject(QWidget *parent)
    : QWidget(parent)
{
    ui.setupUi(this);
    setWindowTitle("Server");
    iniServer();
}
ServerProject::~ServerProject()
{
	closeServer();
	if (m_socket != NULL) {
		delete m_socket;
		m_socket = NULL;
	}
}
void ServerProject::iniServer() {
	//m_sendEnable = false;
	m_filename = "";
	m_fileSize = 0;
	m_sendSize = 0;
	m_socket = NULL;
	ui.clearRecBtn->setEnabled(false);
	ui.sendBtn->setEnabled(false);
	ui.selectBtn->setEnabled(false);
	ui.sendFileBtn->setEnabled(false);
    m_server = new QTcpServer(this);
}
void ServerProject::closeServer() {
	m_server->close();
	if (m_socket == NULL) {
		return;
	}
	//断开与客户端的连接
	if (m_socket->state() == QAbstractSocket::ConnectedState) {
		m_socket->disconnectFromHost();
		if (m_socket->state() != QAbstractSocket::UnconnectedState) {
			m_socket->abort();
		}
	}
}
void ServerProject::on_listenBtn_clicked() {
	if (m_server->isListening()) {
		closeServer();
		//关闭server后恢复界面状态
		ui.listenBtn->setText("Listen");
		ui.addressEt->setEnabled(true);
		ui.portEt->setEnabled(true);
	}
	else {
		//可以使用 QHostAddress::Any 监听所有地址的对应端口
		const QString address_text = ui.addressEt->text();
		const unsigned short port = ui.portEt->text().toUShort();
		const QHostAddress address = (address_text == "Any")
			? QHostAddress::Any
			: QHostAddress(address_text);
		//开始监听,并判断是否成功
		if (m_server->listen(address, port)) {
			//连接成功就修改界面按钮提示,以及地址栏不可编辑
			ui.listenBtn->setText("Close");
			ui.addressEt->setEnabled(false);
			ui.portEt->setEnabled(false);
		}
		connect(m_server, &QTcpServer::newConnection, this, &ServerProject::newConnectionSlot);
	}
}
void ServerProject::newConnectionSlot() {
	if (m_server->hasPendingConnections())
	{
		//nextPendingConnection返回下一个挂起的连接作为已连接的QTcpSocket对象
		//套接字是作为服务器的子级创建的,这意味着销毁QTcpServer对象时会自动删除该套接字。
		//最好在完成处理后显式删除该对象,以避免浪费内存。
		//返回的QTcpSocket对象不能从另一个线程使用,如有需要可重写incomingConnection().
		m_socket = m_server->nextPendingConnection();
		ui.receiveEt->append("connected.........");
		connect(m_socket, &QTcpSocket::readyRead, this, &ServerProject::readyReadSlot);
		ui.clearRecBtn->setEnabled(true);
		ui.selectBtn->setEnabled(true);
		ui.sendBtn->setEnabled(true);
	}
}
void ServerProject::readyReadSlot() {
	if (m_socket->bytesAvailable() <= 0)
		return;
	//注意收发两端文本要使用对应的编解码
	const QString recv_text = QString::fromUtf8(m_socket->readAll());
	if (ui.sendFileBtn->isEnabled()) {
		ui.receiveEt->append(recv_text);
	}
	else {
		if (recv_text == "FileHead Succ") {
			qDebug() << "get FileHead Succ--------------";
			sendData();
		}
		else if (recv_text=="FileRec Done") {
			m_file.close();
			ui.sendBtn->setEnabled(true);
			ui.selectBtn->setEnabled(true);
			ui.sendFileBtn->setEnabled(true);
		}
	}
}
void ServerProject::on_sendBtn_clicked() {
	if (!m_server->isListening())
		return;
	//将发送区文本发送给客户端
	const QByteArray send_data = ui.sendEt->toPlainText().toUtf8();
	//数据为空就返回
	if (send_data.isEmpty())
		return;
	m_socket->write(send_data);
	ui.sendEt->clear();
}
void ServerProject::on_clearRecBtn_clicked() {
	ui.receiveEt->clear();
}
void ServerProject::on_selectBtn_clicked() {
	QString filePath = QFileDialog::getOpenFileName(this, "open", "../");
	if (!filePath.isEmpty()) {
		//m_sendEnable = false;
		m_filename = "";
		m_fileSize = 0;
		m_sendSize = 0;
		QFileInfo info(filePath);
		m_filename = info.fileName();
		m_fileSize = info.size();
		qDebug() << "slectfile name: " << m_filename << " size: " << m_fileSize;
		m_file.setFileName(filePath);
		if (m_file.open(QIODevice::ReadOnly)) {
			//m_sendEnable = true;
			ui.selectBtn->setEnabled(false);
			ui.sendBtn->setEnabled(false);
			ui.sendFileBtn->setEnabled(true);
		}
	}
}
void ServerProject::on_sendFileBtn_clicked() {
	QString filehead = QString("%1#%2").arg(m_filename).arg(m_fileSize);
	qint64 len = m_socket->write(filehead.toUtf8());
	if (len > 0) {
		qDebug() << "filehead:  " << filehead;
		ui.sendFileBtn->setEnabled(false);
	}
}
void ServerProject::sendData() {
	qint64 len = 0;
	do {
		//一次发送的大小
		char buf[BUF_SIZE] = { 0 };
		len = 0;
		len = m_file.read(buf, BUF_SIZE);  //读取的字节数
		len = m_socket->write(buf, len);    //发送的字节数
		qDebug() << "len-----" << len;
		//已发数据累加
		m_sendSize += len;
	} while (len > 0);
}

服务端代码如下:

ClientPro::ClientPro(QWidget *parent)
    : QWidget(parent)
{
    ui.setupUi(this);
    initClient();
}
ClientPro::~ClientPro()
{
	qDebug() << "~ClientPro()----------------------------";
	if (m_client->state() == QAbstractSocket::ConnectedState) {
		//如果使用disconnectFromHost()不会重置套接字,isValid还是会为true
		m_client->abort();
	}
}
void ClientPro::initClient() {
	m_fileMaxsize = 100;
	m_sendEnable = false;
	//创建client对象
	m_client = new QTcpSocket(this);
}
void ClientPro::on_connectBtn_clicked() {
	if (m_client->state() == QAbstractSocket::ConnectedState) {
		//如果使用disconnectFromHost()不会重置套接字,isValid还是会为true
		m_client->abort();
	}
	else if (m_client->state() == QAbstractSocket::UnconnectedState) {
		//从界面上读取ip和端口
		const QHostAddress address = QHostAddress(ui.addressEt->text());
		const unsigned short port = ui.portEt->text().toUShort();
		//连接服务器
		m_client->connectToHost(address, port);
	}
	else {
		ui.receiveEt->append("It is not ConnectedState or UnconnectedState");
	}
	connect(m_client, &QTcpSocket::connected, this, &ClientPro::connectedSlot);
	connect(m_client, &QTcpSocket::disconnected, this, &ClientPro::disconnectedSlot);
	connect(m_client, &QTcpSocket::readyRead, this, &ClientPro::readyReadSlot);
}
void ClientPro::connectedSlot() {
	ui.connectBtn->setText("Disconnect");
	ui.addressEt->setEnabled(false);
	ui.portEt->setEnabled(false);
}
void ClientPro::disconnectedSlot() {
	ui.connectBtn->setText("Connect");
	ui.addressEt->setEnabled(true);
	ui.portEt->setEnabled(true);
}
void ClientPro::readyReadSlot() {
	if (m_client->bytesAvailable() <= 0)
		return;
	//注意收发两端文本要使用对应的编解码
	QByteArray buf = m_client->readAll();
	const QString recv_text = QString::fromUtf8(buf);

	QStringList list = recv_text.split("#");
	qDebug() << "listsize: " << list.size();
	if (!m_sendEnable&&list.size() == 2) {
		m_sendEnable = true;
		ui.sendBtn->setEnabled(false);
		m_recSize = 0;
		m_client->write("FileHead Succ");
		m_file.setFileName(list[0]);
		m_fileMaxsize = list[1].toInt();
		ui.progressBar->setValue(m_recSize);
		ui.progressBar->setMaximum(m_fileMaxsize);
		if (m_file.open(QIODevice::WriteOnly)) {
			return;
		}
	}
	if (!m_sendEnable) {
		ui.receiveEt->append(recv_text);
	}
	else {
		qint64 len = m_file.write(buf);
		m_recSize += len;
		qDebug() << "client----m_recSize: " << m_recSize;
		ui.progressBar->setValue(m_recSize);
		if (m_recSize == m_fileMaxsize) {
			qDebug() << "rec done--------------";
			m_sendEnable = false;
			m_file.close();
			m_client->write("FileRec Done");
			ui.sendBtn->setEnabled(true);
		}
	}
}
void ClientPro::on_sendBtn_clicked() {
	if (!m_client->isValid())
		return;
	//将发送区文本发送给客户端
	const QByteArray send_data = ui.sendEt->toPlainText().toUtf8();
	//数据为空就返回
	if (send_data.isEmpty())
		return;
	m_client->write(send_data);
}
void ClientPro::on_clearRecBtn_clicked() {
	ui.receiveEt->clear();
}
void ClientPro::on_clearSendBtn_clicked() {
	ui.sendEt->clear();
}

动态显示如下:
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt使用网络通信传输数据库文件,你可以按照以下步骤进行操作: 1. 将需要传输的数据库文件拆分成较小的块(chunks)或者按照需要传输的大小进行分割。 2. 使用Qt的网络模块建立服务器和客户端之间的连接。服务器端负责监听客户端的连接请求,而客户端则负责与服务器建立连接。 3. 在服务器端,当接收到客户端的连接请求后,将数据库文件的块逐个发送给客户端。你可以使用`QTcpServer`和`QTcpSocket`类来实现这一过程。 ```cpp QTcpServer server; QTcpSocket* clientConnection; // 等待客户端连接 server.listen(QHostAddress::Any, port); connect(&server, &QTcpServer::newConnection, this, [=]() { clientConnection = server.nextPendingConnection(); // 发送数据库文件块给客户端 sendDatabaseChunks(clientConnection); }); // 发送数据库文件块 void sendDatabaseChunks(QTcpSocket* socket) { QFile file("path/to/database/file"); if (!file.open(QIODevice::ReadOnly)) { qDebug() << "Error opening database file"; return; } while (!file.atEnd()) { QByteArray chunk = file.read(chunkSize); socket->write(chunk); socket->waitForBytesWritten(); } file.close(); socket->disconnectFromHost(); } ``` 4. 在客户端,连接到服务器并接收来自服务器端的数据库文件块。你可以使用`QTcpSocket`类来实现这一过程。 ```cpp QTcpSocket socket; // 连接到服务器 socket.connectToHost(serverAddress, port); if (!socket.waitForConnected()) { qDebug() << "Failed to connect to the server"; return; } // 接收数据库文件块 QByteArray databaseFile; while (socket.bytesAvailable() > 0) { QByteArray chunk = socket.read(chunkSize); databaseFile.append(chunk); } socket.disconnectFromHost(); ``` 5. 在客户端接收到所有数据库文件块后,可以将它们合并成完整的数据库文件。 请注意,以上代码只是示例,你需要根据实际情况进行适当的修改和调整。另外,网络通信涉及到数据安全性和完整性的问题,你可能需要考虑使用加密算法和校验机制来保证传输的安全性和准确性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值