Qt实现TCP文件服务器(服务器发送文件)

简述

TCP文件服务器的实现,可以在TCP服务器的基础上增加文件发送逻辑。参阅TCP文件服务器的实现。【https://blog.csdn.net/lusanshui/article/details/88565806

代码之路

直接给出完整的TCP文件服务器代码。
MyFileServer类的头文件如下:

#include <QTcpServer>
#include <QTcpSocket>
#include <QDataStream>
#include <QFile>
#include <QHostAddress>
#include <QIODevice>
#include <QThread>

class MyFileServer : public QObject
{
	Q_OBJECT
public:
	MyFileServer(QObject *parent = 0);
	~MyFileServer();
signals:
	void startSendFile(QString filename);
private slots:
	void acceptFileConnection();
	void updateFileProgress();
	void displayError(QAbstractSocket::SocketError socketError);
	void filesocketDisconnect();
	void sendFile(QString filename);
private:
	QString getFileFullPath(QString tmp); //获取待发送的文件路径
private:
	QTcpServer *fileserver;
	QTcpSocket *filesocket;
	QThread *m_thread;
	
	MyDatastream m_DATAstream;
	SingleFile m_SingleFile;	
}

MyFileServer类的源文件如下:

MyFileServer::MyFileServer(QObject *parent) : QObject(parent)
{
	m_thread = new QThread();
	filesocket = new QTcpSocket();
	fileserver = new QTcpServer();
	//listening
	fileserver->listen(QHostAddress::Any, 6001);
	connect(fileserver, SIGNAL(newConnection()), this, SLOT(acceptFileConnection()));
	filesocket->moveToThread(m_thread);
	fileserver->moveToThread(m_thread);
	this->moveToThread(m_thread);
	m_thread->start();
}

MyFileServer::~MyFileServer()
{
	m_thread->quit();
	m_thread->wait();
	delete m_thread;
	filesocket->close();
	delete filesocket;
	fileserver->close();
	delete fileserver;
}

void MyFileServer::acceptFileConnection()
{
	filesocket = fileserver->nextPendingConnection();
	connect(filesocket, SIGNAL(readyRead()), this, SLOT(updateFileProgress()));
	connect(filesocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(displayError(QAbstractSocket::SocketError)));
	connect(filesocket, SIGNAL(disconnected()), this, SLOT(filesocketDisconnect()));
	connect(this, SIGNAL(startSendFile(QString)), this, SLOT(sendFile(QString)));
}

void MyFileServer::updateFileProgress()
{
	//receive msg
	if (filesocket->bytesAvailable() <= 0)
	{
		return;
	}
	QByteArray singleBuffer = filesocket->readAll();
	if (singleBuffer.size() == 14 && singleBuffer[0] == 0xF7) //双方约定
	{
		m_SingleFile = m_DATAstream.ReadSingleFile(singleBuffer); //按约定转信息,得到文件名等信息
		QString tmpFilename = m_SingleFile.fileDataInfo.strName;
		QString tmpFullFilename = getFileFullPath(tmpFilename); //根据文件名得到全路径
		emit startSendFile(tmpFullFilename);
	}
}

void MyFileServer::displayError(QAbstractSocket::SocketError socketError)
{
	qDebug() << filesocket->errorString();
	filesocket->close();
}

void MyFileServer::filesocketDisconnect()
{
	filesocket->deleteLater();
}

void MyFileServer::sendFile(QString filename)
{
	QFile localFile(filename);
	if (!localFile.open(QFile::ReadOnly))
	{
		qDebug() << "cannot open file which need to send!";
		return;
	}
	QByteArray  totalba = localFile.readAll();
	filesocket->write(totalba);
}

QString MyFileServer::getFileFullPath(QString tmp)
{
	QString fullpath;
	//...
	return fullpath;
}

总结

文中监听端口号6001,每收到约定好的字符串文件发送请求,解析文件名并发送文件内容。
在工程的pro文件中不要忘记把network模块加入进来。

发布了47 篇原创文章 · 获赞 45 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/lusanshui/article/details/88566640