使用QT实现FTP客户端与服务端(1)

1.实现FTP客户端

作为FTP客户端,需要主动发起连接至服务端所在ip的默认21号端口,连接步骤与数据交互如下:
1.客户端链接服务器端口
2.客户端分步输入用户名密码
3.(可选)客户端输入数据传输模式,默认为被动模式,可主动切换为主动模式(在一些机器上被禁用,需手动开启)
4.输入操作指令
5.根据数据传输模式建立数据连接。(5*进行数据传输)
6.退出
1)h文件

#include 
#include 
#include 
#include 
#include 

#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 
#include 

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;

你可能感兴趣的:(C++)