Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Qt Academy Launch in California!

    FTPClient using QTcpSocket and signals and slots

    General and Desktop
    2
    14
    4091
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • R
      robsonQTnewbie last edited by

      Hi everybody, I'm writing a FTP client application. This is the logic of the first project, where I stuck:

      1. The network communication is based on QTcpSocket - I made one class responsible for making a command-transmision socket. In the class socketconnection was one public function named test() responsible starting the communication. In this function was also a signal_and_slot_connection: connect(socket, SIGNAL(connected()), this, SLOT(connected())); Then the class socketconnection had a private function connected() that made the whole communication. I send from there every FTP command, etc... So i was able to send messages to the ftp server and getting answers and it works fine, this way I recieved a directory listing from the server (command LIST) - for this I must made a data-transfer socket. I works.

      And here comes the problem, because I'm clicking on one button in my application ("Connect"), the necessary connecting information was in some line edits but that works fine. The problem is, that now i need to transfer files. I got two buttons in the mainwindow. ("Download" and "Store") and I have no ide how get from this buttons acces to the command-transfer socket.

      I decided to change my project and make it better (logically)
      Changes i wanna make:
      -After clicking Connect-button (from mainwindow) the connection should be made (via command-transmision socket)
      -Next a method responsible for the directory listing should be defined (she must have access to the command-transmision socket) i this step i data-transmision socket should be also created for the directory listing.
      -After clicking the "Download" or "STORE" button the file transfer is starting. (Like the directory listing i think)

      Where is the problem? I Can't make the right communication between the ui components and the socketconnection class. I have no idea how get access to the UI:MainWindow *ui object and use it as a SIGNAL object.

      THANKS A LOT for every help from you guys.
      P.S. Sorry for my bad english :(

      1 Reply Last reply Reply Quote 0
      • SGaist
        SGaist Lifetime Qt Champion last edited by

        Hi and welcome to devnet,

        Without seeing your code, it's pretty much crystal ball debugging. Can you share it ?

        Out of curiosity, are you tied to QTcpSocket ?

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply Reply Quote 0
        • R
          robsonQTnewbie last edited by

          Hi, thank you for the reply:) Infortunately I can use only QTcpSocket for this project :/ It's the requirement to pass the course ony my studies.

          Here come's my source code and a screenshot from the project so you can see what files I have.
          !http://przeklej.org/file/vlK2gP/snapshot1.png(QTCreator-snapshot)!

          MAINWINDOW.h:
          @#ifndef MAINWINDOW_H
          #define MAINWINDOW_H

          #include <QMainWindow>
          #include <exitdialog.h>
          #include <QString>
          #include <QDirModel>

          namespace Ui {
          class MainWindow;
          }

          class MainWindow : public QMainWindow
          {
          Q_OBJECT

          public:
          explicit MainWindow(QWidget *parent = 0);
          ~MainWindow();
          void Refresh();
          QString url, login, password, port;
          private slots:
          void on_actionZako_cz_triggered();

          void on_actionKonfiguruj_triggered();
          
          void on_pushButton_clicked();
          
          void on_pushButton_3_clicked();
          
          void on_pushButton_2_clicked();
          
          void on_pushButton_5_clicked();
          

          private:
          QDirModel dirModel;
          Ui::MainWindow *ui;
          void addRoot(QString name, QString size, QString type);
          };

          #endif // MAINWINDOW_H
          @

          1 Reply Last reply Reply Quote 0
          • R
            robsonQTnewbie last edited by

            MAINWINDOW.cpp
            @#include "mainwindow.h"
            #include "ui_mainwindow.h"
            #include "exitdialog.h"
            #include "konfigurujdialog.h"
            #include "socketconnection.h"
            #include <QMessageBox>
            #include <stdio.h>
            #include <QRegExp>

            MainWindow::MainWindow(QWidget *parent) :
            QMainWindow(parent),
            ui(new Ui::MainWindow)
            {
            ui->setupUi(this);
            Refresh();
            }

            MainWindow::~MainWindow()
            {
            delete ui;
            }

            void MainWindow::on_actionZako_cz_triggered()
            {
            ExitDialog *exit = new ExitDialog();
            exit->setModal(true);
            exit->exec();
            }

            void MainWindow::on_actionKonfiguruj_triggered()
            {
            KonfigurujDialog *konfig = new KonfigurujDialog();
            konfig->setModal(true);
            konfig->exec();
            }

            void MainWindow::on_pushButton_clicked() //connect button
            {
            ui->textBrowser->clear();
            ui->treeWidget_2->clear();
            url = ui->urlValue->text();
            login = ui->loginValue->text();
            password = ui->passwordValue->text();
            port = ui->portValue->text();

            socketconnection *s = new socketconnection(url, login, password, port);
            QString komunikat, komunikat2;
            QString* listaFolderow;
            QString* sciezkaFolderow;
            komunikat = s->test();                 
            listaFolderow = &(s->directoryList);   // downloading the content from the public variable that's carreing the dirlisting
            sciezkaFolderow = &(s->currentPath);   // downloading the content from the public variable that's carreing the currentpath on the ftp server
            ui->textBrowser->insertPlainText(komunikat);
            
            
            QRegExp regex1("\n");
            QRegExp regex2("[ ]+|\n");
                                        
            std::string DirPath = sciezkaFolderow->toStdString();
            *sciezkaFolderow = "";
            for(int i = 0; i < DirPath.length(); i++)
            {
                int j = i+1;
                if(DirPath[i] == '\"')
                {
                    while(DirPath[j] != '\"')
                    {
                        *sciezkaFolderow += DirPath[j];
                        j++;
                    }
                    break;
                }
            }
            qDebug() << *sciezkaFolderow;
            
            ui->lineEdit_6->setText(*sciezkaFolderow);
            
            QStringList listing;                    //  lista zawierająca całe wiersze listingu plików
            listing = listaFolderow->split(regex1);
            
            std::string part;
            std::string partI, partII;
            QStringList QpartI;
            
            int i = 0, globalCounter = 0;
            foreach (QString var, listing)
                globalCounter++;
            QString czyFolder[globalCounter], Rozmiar[globalCounter], Nazwa[globalCounter];
            
            foreach (QString var, listing)
            {
               part = var.toStdString();
               int licznik = 0;
               for(int j = 0; j < part.length(); j++)
               {
                   if(licznik < 55)
                       partI += part[j];
                   else
                   {
                       if(licznik == part.length()-1)
                           break;
                       partII += part[j];
                   }
                   licznik++;
               }
            
               QpartI << QString::fromStdString(partI).split(regex2);
               Nazwa[i] = QString::fromStdString(partII);
               partI = "";
               partII = "";
               i++;
            }
            QpartI.removeAll("");
            i = 0;
            int j = 0;
            foreach(QString var, QpartI)
            {
                i++;
                if(i == 1)
                {
                    if(var.left(1) == "d")
                        czyFolder[j] = "Directory";
                    else
                        czyFolder[j] = "File";
                }
                if(i == 5)
                    Rozmiar[j] = var;
            
                if(i == 8)
                {
                    i = 0;
                    j++;
                }
            }
            for(i = 0; i < globalCounter; i++)
            {
                addRoot(Nazwa[i], Rozmiar[i], czyFolder[i]);
            }
            

            }

            void MainWindow::addRoot(QString name, QString size, QString type)
            {
            QTreeWidgetItem pWidgetItem = new QTreeWidgetItem(ui->treeWidget_2);
            pWidgetItem->setText(0, name);
            pWidgetItem->setText(1, size);
            pWidgetItem->setText(2, type);
            ui->treeWidget_2->addTopLevelItem(pWidgetItem);
            }
            void MainWindow::Refresh()
            {
            dirModel.setParent(this);
            dirModel.setReadOnly(false);
            QDirModel
            model = &dirModel;
            ui->treeView->setModel(model);

            model->setSorting(QDir::DirsFirst | QDir::IgnoreCase | QDir::Name);
            
            QModelIndex index = model->index("/");
            ui->treeView->expand(index);
            ui->treeView->scrollTo(index);
            ui->treeView->setCurrentIndex(index);
            ui->treeView->resizeColumnToContents(0);
            
            // geting the filepath
            
            QFileInfo informacja;
            index = ui->treeView->currentIndex();
            informacja = model->fileInfo(index);
            ui->lineEdit->setText(informacja.filePath());
            

            }

            void MainWindow::on_pushButton_3_clicked() //button do przodu sekcji KOMPUTER LOKALNY
            {
            QDirModel* model = &dirModel;
            QModelIndex index = ui->treeView->currentIndex();
            ui->treeView->expand(index);
            QFileInfo informacja = model->fileInfo(index);
            ui->lineEdit->setText(informacja.filePath());
            index = ui->treeView->indexBelow(ui->treeView->currentIndex());

            ui->treeView->setCurrentIndex(index);
            

            }

            void MainWindow::on_pushButton_2_clicked() //button cofnij sekcji KOMPUTER LOKALNY
            {
            QDirModel* model = &dirModel;
            ui->treeView->collapse(ui->treeView->currentIndex());
            QModelIndex index = ui->treeView->indexAbove(ui->treeView->currentIndex());
            // QModelIndex index = ui->treeView->indexAbove(ui->treeView->currentIndex());

            ui->treeView->setCurrentIndex(index);
            QFileInfo informacja = model->fileInfo(index);
            ui->lineEdit->setText(informacja.filePath());
            

            }

            void MainWindow::on_pushButton_5_clicked() //butto do przodu sekcji SERWER
            {

            }
            @

            1 Reply Last reply Reply Quote 0
            • R
              robsonQTnewbie last edited by

              SOCKETCONNECTION.h
              @#ifndef SOCKETCONNECTION_H
              #define SOCKETCONNECTION_H

              #include <QMainWindow>
              #include <QObject>
              #include <iostream>
              #include <QTcpSocket>
              #include <QAbstractSocket>
              #include <QString>

              class socketconnection : public QObject
              {
              Q_OBJECT
              public:
              explicit socketconnection(QString url, QString login, QString password, QString port, QObject *parent = 0);
              QString test();
              QString komunikat, message, command;
              QString url, login, password, port;
              QString directoryList; //pointer to the downloaded directory listing
              QString currentPath;
              signals:

              public slots:
              void connected();
              private:
              QTcpSocket *socket;
              QTcpSocket socketTransmit;
              };

              #endif // SOCKETCONNECTION_H
              @

              1 Reply Last reply Reply Quote 0
              • R
                robsonQTnewbie last edited by

                SOCKETCONNECTION.cpp
                @#include "socketconnection.h"
                #include "mainwindow.h"
                #include <stdio.h>
                socketconnection::socketconnection(QString url, QString login, QString password, QString port, QObject *parent) :
                QObject(parent)
                {
                this->url = url;
                this->login = login;
                this->password = password;
                this->port = port;
                }
                QString socketconnection::test(){
                komunikat = "Status: ";
                socket = new QTcpSocket(this);
                connect(socket, SIGNAL(connected()), this, SLOT(connected()));
                komunikat += "Łączenie do serwera FTP...\n";
                socket->connectToHost((url.toUtf8().constData()), port.toShort());
                if(!socket->waitForConnected(3000)){
                komunikat += "Message: ";
                komunikat += "Przekroczony limit czasu...\n";
                }
                return komunikat;
                }
                void socketconnection::connected()
                {
                QString adresIP, transfer_port;
                std::string passive_connection = "";
                std::string oktet[6];
                int licznik = 0, portA, portB, portC;
                komunikat += "Message: ";
                while(message.length() == 0) message = socket->readLine();
                komunikat += message;
                komunikat += "Polecenie: ";
                message = "";
                command = "USER " + login + "\r\n";
                komunikat += "Polecenie: ";
                komunikat += command;
                socket->write(command.toUtf8().constData());
                socket->waitForBytesWritten(5000);
                while(message.length() == 0) message = socket->readLine();
                komunikat += "Message: ";
                komunikat += message;
                message = "";
                command = "PASS " + password + "\r\n";
                komunikat += "Polecenie: PASS <nie pokażę Ci hasła>\n";
                socket->write(command.toUtf8().constData());
                socket->waitForBytesWritten(5000);
                while(message.length() == 0) message = socket->readLine();
                komunikat += "Message: ";
                komunikat += message;
                message = "";
                command = "OPTS UTF8 ON\r\n";
                komunikat += "Polecenie: ";
                komunikat += command;
                socket->write(command.toUtf8().constData());
                socket->waitForBytesWritten(5000);
                while(message.length() == 0) message = socket->readLine();
                komunikat += "Message: ";
                komunikat += message;
                message = "";
                komunikat += "Status: Connected succesfully. Now I'm checking the directory list...\n";
                command = "TYPE I\r\n";
                komunikat += "Polecenie: ";
                komunikat += command;
                socket->write(command.toUtf8().constData());
                socket->waitForBytesWritten(5000);
                while(message.length() == 0) message = socket->readLine();
                komunikat += "Message: ";
                komunikat += message;
                message = "";
                command = "PWD \r\n";
                komunikat += "Polecenie: ";
                komunikat += command;
                socket->write(command.toUtf8().constData());
                socket->waitForBytesWritten(5000);
                int i = 0;
                while(message.length() == 0){
                message = socket->readLine();
                }
                currentPath = message;
                komunikat += "Message: ";
                komunikat += message;
                message = "";
                command = "PASV \r\n";
                komunikat += "Polecenie: ";
                komunikat += command;
                socket->write(command.toUtf8().constData());
                socket->waitForBytesWritten(5000);
                while(message.length() == 0) message = socket->readLine();
                komunikat += "Message: ";
                komunikat += message;
                passive_connection = message.toUtf8().constData();
                message = "";
                for(int i = 3; i < passive_connection.length()-2; i++){
                if(passive_connection[i] >= '0' && passive_connection[i] <= '9'){
                oktet[licznik] += passive_connection[i];
                if(passive_connection[i+1] == ',')
                {
                licznik++;
                continue;
                }
                }
                }
                adresIP = QString::fromStdString(oktet[0]) + "." + QString::fromStdString(oktet[1]) + "." + QString::fromStdString(oktet[2])
                + "." + QString::fromStdString(oktet[3]);
                portA = QString::fromStdString(oktet[4]).toInt();
                portB = QString::fromStdString(oktet[5]).toInt();
                portC = (portA * 256 + portB);
                transfer_port.setNum(portC);
                komunikat += "Tworzę połączenie na następujący adres i port: \n";
                komunikat += "Adres: " + adresIP + "\n";
                komunikat += "Port: " + transfer_port + "\n";

                    socketTransmit.connectToHost(adresIP, portC);
                    socketTransmit.waitForConnected(2000);
                    komunikat += "Polecenie: ";
                    command = "LIST \r\n";
                    komunikat += command;
                    socket->write(command.toUtf8().constData());
                    socket->waitForBytesWritten(5000);              
                    socketTransmit.waitForBytesWritten(5000);
                    socketTransmit.waitForReadyRead(5000);
                    socket->waitForBytesWritten(5000);
                
                    socket->waitForBytesWritten(5000);
                    message = socket->readLine();  //czekamy na odpowiedź kolejną z socketu poleceń
                    komunikat += "Message: ";
                    komunikat += message;
                    message = "";
                
                    message = socketTransmit.readAll();
                    directoryList = message;    //  pobieramy do zmiennej directoryList listing plików i folderów
                    if (directoryList != ""){
                        komunikat += "Listing plików i folderów przesłąny z powodzeniem!!!:\n";
                    }
                    else
                        komunikat += "Błąd! Nie udało mi się pobrać listy plików i folderów!!!\n";
                    //komunikat += message;
                    message = "";
                    i = 0;
                    while(message.length() == 0){
                        i++;
                        message = socket->readLine();
                        if(i == 32768)
                        {
                            message = "Błąd podczas transmisji polecenia";
                            break;
                        }
                    }
                    komunikat += "Message: ";
                    komunikat += message;
                    message = "";
                }
                

                @

                1 Reply Last reply Reply Quote 0
                • R
                  robsonQTnewbie last edited by

                  I know my code isn't nice but I've just started my QT experience, so I hope that you'll understand and can help me. Thanks a lot :)

                  1 Reply Last reply Reply Quote 0
                  • SGaist
                    SGaist Lifetime Qt Champion last edited by

                    There are indeed several things that I don't follow:

                    • Why are you mixing std::string and QString ? Currently it just complicates your code without any benefits
                    • Why are you using pointers to QString ?

                    You are also creating memory leaks with your custom dialogs.

                    Anyway, for your original problem. You are doing everything in the connected slot, which is a bad idea. You need to refactor that and split the logic for the various commands you want to send in their own functions

                    Interested in AI ? www.idiap.ch
                    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                    1 Reply Last reply Reply Quote 0
                    • R
                      robsonQTnewbie last edited by

                      I'm mixing QString with std::string because I couldn't filter the QString like a simple array, so I decided to go on the easiest way and parse it to std::string.

                      I need pointers to QString because I have no idea how get access to one variable from one class in another class. I think pointers are a good method to get the content from variables....

                      Which custom dialogs do you mean? I thinked about your advice to split to signal and slot system but I have trouble with it..... now i have something like that:
                      @#include "mainwindow.h"
                      #include "ui_mainwindow.h"

                      MainWindow::MainWindow(QWidget *parent) :
                      QMainWindow(parent),
                      ui(new Ui::MainWindow)
                      {
                      ui->setupUi(this);
                      }

                      MainWindow::~MainWindow()
                      {
                      delete ui;
                      }

                      void MainWindow::on_pushButton_clicked() // connect Button
                      {
                      commandSocket = new QTcpSocket(this);

                      login = ui->loginValue->text();
                      url = ui->urlValue->text();
                      password = ui->passwordValue->text();
                      port = ui->portValue->text();
                      qint64 timeout = 4000;
                      
                      connect(commandSocket, SIGNAL(connected()), this, SLOT(connected()));
                      connect(commandSocket, SIGNAL(bytesWritten(timeout)), this, SLOT(getMessage()));
                      qDebug() << "Connecting...";
                      
                      commandSocket->connectToHost(url, port.toShort());
                      if(!commandSocket->waitForConnected(3000)){
                          qDebug() << "Przekroczony limit czasu...\n";
                      }
                      

                      }

                      void MainWindow::connected()
                      {
                      qDebug() << "In connected()...";
                      sendMessage("USER ", login);

                      }
                      void MainWindow::sendMessage(QString message, QString argument)
                      {
                      qDebug() << "in sendMessage...";
                      QString displayedArgument, command;
                      if(message == "PASS ")
                      displayedArgument = "SECRET_PASSWORD...";
                      else
                      displayedArgument = argument;
                      command = message + argument + "\r\n";
                      commandSocket->write(command.toUtf8().constData());
                      commandSocket->waitForBytesWritten(10000);

                      ui->textBrowser->setOverwriteMode(false);
                      ui->textBrowser->setText("Polecenie: " + message + displayedArgument + "\n");
                      qDebug() << "send message done...";
                      

                      }
                      void MainWindow::getMessage()
                      {
                      qDebug() << "In getMessage()...";
                      QString message = "";
                      //while(message == "")
                      message = commandSocket->readLine();

                      qDebug() << message;
                      ui->textBrowser->setOverwriteMode(false);
                      ui->textBrowser->setText(message);
                      

                      }@
                      and unfortunately it's not working:/
                      PS. I decidet to put everything in the mainwindow.cpp.

                      1 Reply Last reply Reply Quote 0
                      • SGaist
                        SGaist Lifetime Qt Champion last edited by

                        What do you mean by "can't filter like a simple array" ?

                        You should have a look at the fortune client/server example for inspiration

                        Interested in AI ? www.idiap.ch
                        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                        1 Reply Last reply Reply Quote 0
                        • R
                          robsonQTnewbie last edited by

                          I mean something like that:
                          @
                          QString someQString = "I like Qt!", outputQString = "";
                          for(int i = 0; i < someQString.length(); i++)
                          {
                          if(someQString[i] != " ")
                          outputString += someQString[i];
                          }
                          @

                          1 Reply Last reply Reply Quote 0
                          • SGaist
                            SGaist Lifetime Qt Champion last edited by

                            You want to remove all white spaces in the string ?
                            From the top of my head:
                            @
                            someQString.replace(QRegular[removed]"\s"), "");
                            @

                            Replace QRegularExpression by QRegExp if you are on Qt 4

                            Interested in AI ? www.idiap.ch
                            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                            1 Reply Last reply Reply Quote 0
                            • R
                              robsonQTnewbie last edited by

                              Thanks:) I moved forward with my project and now i need help with downloading files. The problem is that, when I download a file (first .txt) the data go on the socket but not everything. When i download a small file it works fine, but when I download a bigger file it looses data. :/ Do you have a advice form me?

                              P.S. I start the download from the transfer socket, when on the commandLineSocket is the command RETR succesfully transmited.

                              1 Reply Last reply Reply Quote 0
                              • SGaist
                                SGaist Lifetime Qt Champion last edited by

                                Look at readyRead and the asynchronousness handling of IO devices

                                Interested in AI ? www.idiap.ch
                                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                                1 Reply Last reply Reply Quote 0
                                • First post
                                  Last post