1.实现FTP客户端
作为FTP客户端,需要主动发起连接至服务端所在ip的默认21号端口,连接步骤与数据交互如下:
1.客户端链接服务器端口
2.客户端分步输入用户名密码
3.(可选)客户端输入数据传输模式,默认为被动模式,可主动切换为主动模式(在一些机器上被禁用,需手动开启)
4.输入操作指令
5.根据数据传输模式建立数据连接。(5*进行数据传输)
6.退出
1)h文件
#include <QFile>
#include <QObject>
#include <QTcpSocket>
#include <QTcpServer>
#include <QTextCodec>
#include "string.h"
class FtpClientCollecor : public QObject
{
Q_OBJECT
public:
explicit FtpClientCollecor(QObject *parent = nullptr);
public:
void doConnect();
void sendDataMsg(const std::string &msg, const int &length);
private slots:
void ClientPORTCtrlRecvData();
void ClientRecvData();
void ClientPASVCtrlRecvData();
void ConnectionFromClient();
void serverErrorConnection();
private:
QTcpSocket *m_tcpSocket;
QTcpServer *m_tcpServer;
QTcpSocket *m_tcpDataSocket;
QString m_userName;
QString m_passWord;
QString m_serverIP;
int m_serverPort;
int i; // 交互次数
};
2)cpp文件
#include "ftpmanager.h"
#include <QDebug>
#include <QHostAddress>
FtpClientCollecor::FtpClientCollecor(QObject *parent):QObject(parent)
{
m_tcpServer = new QTcpServer(this);
m_tcpSocket = new QTcpSocket(this);
m_tcpDataSocket = new QTcpSocket(this);
connect(m_tcpServer, SIGNAL(newConnection()), this, SLOT(ConnectionFromClient()));
// connect(m_tcpSocket, SIGNAL(readyRead()), this, SLOT(ClientPORTCtrlRecvData()));
connect(m_tcpSocket, SIGNAL(readyRead()), this, SLOT(ClientPASVCtrlRecvData()));
i = 0;
doConnect();
}
void FtpClientCollecor::doConnect()
{
m_serverIP = "xxx.xxx.xxx.xxx";
m_serverPort = 21;
if (m_serverIP.isEmpty())
qCritical() << "IP is Empty!";
m_tcpSocket->connectToHost(QHostAddress(m_serverIP), m_serverPort);
if (!m_tcpSocket->waitForConnected(30000))
{
qDebug() << "服务器连接失败";
}
else
{
qDebug() << "服务器连接成功";
std::string sendData = "USER user\r\n";
sendDataMsg(sendData.c_str(), sendData.size());
}
}
void FtpClientCollecor::sendDataMsg(const std::string &msg, const int &length)
{
QByteArray sendMsgArray;
sendMsgArray.append(msg.c_str(), length);
m_tcpSocket->write(sendMsgArray);
}
void FtpClientCollecor::ClientPORTCtrlRecvData()
{
i++;
if (!m_tcpSocket->bytesAvailable())
return;
QByteArray recvDatas = m_tcpSocket->readAll();
qDebug() << "收到数据:";
qDebug() << recvDatas;
if (i == 2)
{
std::string sendData = "PASS 123456\r\n";
sendDataMsg(sendData.c_str(), sendData.size());
}
if (i == 3)
{
std::string sendData = "PORT xxx,xxx,xxx,xxx,250,103\r\n";
sendDataMsg(sendData.c_str(), sendData.size());
}
if (i == 4)
{
m_tcpServer->listen(QHostAddress::Any, 64103);
std::string sendData = "RETR test.txt\r\n";
sendDataMsg(sendData.c_str(), sendData.size());
qDebug() << "发送通信请求";
}
}
void FtpClientCollecor::ClientPASVCtrlRecvData()
{
i++;
if (!m_tcpSocket->bytesAvailable())
return;
QByteArray recvDatas = m_tcpSocket->readAll();
qDebug() << "收到数据:";
qDebug() << recvDatas;
if (i == 2)
{
std::string sendData = "PASS 123456\r\n";
sendDataMsg(sendData.c_str(), sendData.size());
}
if (i == 3)
{
std::string sendData = "PASV \r\n";
sendDataMsg(sendData.c_str(), sendData.size());
}
if (i == 4)
{
QString sql = recvDatas;
QStringList list1 = sql.split("(");
QString listRight = list1[1];
QStringList list2 = listRight.split(")");
QString listLeft = list2[0];
QStringList listIPPort = listLeft.split(",");
int port = QString(listIPPort[4]).toInt() * 256 + QString(listIPPort[5]).toInt();
m_tcpDataSocket->connectToHost(m_serverIP, port);
connect(m_tcpDataSocket, SIGNAL(readyRead()), this, SLOT(ClientRecvData()));
std::string sendData = "RETR file.txt\r\n";
sendDataMsg(sendData.c_str(), sendData.size());
}
}
void FtpClientCollecor::ClientRecvData()
{
if (m_tcpServer->isListening())
{
m_tcpServer->close();
}
if (!m_tcpDataSocket->bytesAvailable())
return;
QByteArray recvDatas = m_tcpDataSocket->readAll();
// 转换中文字符
QTextCodec *tc = QTextCodec::codecForName("GBK");
QString recvDataString = tc->toUnicode(recvDatas);
qDebug() << recvDataString;
QFile file("F:/file.txt");
QTextStream out(&file);
if(file.open(QFile::WriteOnly|QFile::Truncate))
{
out << recvDataString;
}
std::string sendData = "QUIT\r\n";
sendDataMsg(sendData.c_str(), sendData.size());
QByteArray sendMsgArray;
sendMsgArray.append(sendData.c_str(), sendData.size());
m_tcpDataSocket->write(sendMsgArray);
qDebug() << "再见";
}
void FtpClientCollecor::ConnectionFromClient()
{
m_tcpDataSocket = m_tcpServer->nextPendingConnection();
connect(m_tcpDataSocket, SIGNAL(readyRead()), this, SLOT(ClientRecvData()));
}
void FtpClientCollecor::serverErrorConnection()
{
qDebug() << m_tcpServer->errorString();
}
3)main.cpp
FtpClientCollecor p;